Skip to content
This repository was archived by the owner on May 16, 2019. It is now read-only.

Commit 60f1b7b

Browse files
committed
Refactor notifications handling
1 parent c9d380c commit 60f1b7b

19 files changed

+234
-114
lines changed

api/restapi.py

+17-12
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,25 @@
22
import json
33
import os
44
import pickle
5+
from binascii import unhexlify
6+
from collections import OrderedDict
7+
58
from txrestapi.resource import APIResource
69
from txrestapi.methods import GET, POST, DELETE
710
from twisted.web import server
811
from twisted.web.resource import NoResource
912
from twisted.web import http
1013
from twisted.internet import defer, reactor
11-
from binascii import unhexlify
12-
from constants import DATA_FOLDER
1314
from twisted.protocols.basic import FileSender
15+
16+
from constants import DATA_FOLDER
1417
from protos.countries import CountryCode
1518
from protos import objects
1619
from keyutils.keys import KeyChain
1720
from dht.utils import digest
1821
from market.profile import Profile
1922
from market.contracts import Contract
20-
from collections import OrderedDict
21-
from upnp import PortMapper
23+
from net.upnp import PortMapper
2224

2325
DEFAULT_RECORDS_COUNT = 20
2426
DEFAULT_RECORDS_OFFSET = 0
@@ -538,7 +540,8 @@ def purchase_contract(self, request):
538540
try:
539541
def handle_response(resp, contract):
540542
if resp:
541-
contract.await_funding(self.protocol.ws, self.protocol.blockchain, resp)
543+
contract.await_funding(self.mserver.protocol.get_notification_listener(),
544+
self.protocol.blockchain, resp)
542545
request.write(json.dumps({"success": True, "payment_address": payment[0],
543546
"amount": payment[1],
544547
"order_id": c.get_contract_id().encode("hex")},
@@ -765,10 +768,12 @@ def get_notifications(self, request):
765768
"id": n[0],
766769
"guid": n[1].encode("hex"),
767770
"handle": n[2],
768-
"message": n[3],
769-
"timestamp": n[4],
770-
"avatar_hash": n[5].encode("hex"),
771-
"read": False if n[6] == 0 else True
771+
"type": n[3],
772+
"order_id": n[4],
773+
"title": n[5],
774+
"timestamp": n[6],
775+
"image_hash": n[7].encode("hex"),
776+
"read": False if n[8] == 0 else True
772777
}
773778
notification_list.append(notification_json)
774779
request.write(json.dumps(notification_list, indent=4))
@@ -787,13 +792,13 @@ def mark_as_read(self, request):
787792
request.finish()
788793
return server.NOT_DONE_YET
789794

790-
@POST('^/api/v1/send_notification')
791-
def send_notification(self, request):
795+
@POST('^/api/v1/broadcast')
796+
def broadcast(self, request):
792797
try:
793798
def get_response(num):
794799
request.write(json.dumps({"success": True, "peers reached": num}, indent=4))
795800
request.finish()
796-
self.mserver.send_notification(request.args["message"][0]).addCallback(get_response)
801+
self.mserver.broadcast(request.args["message"][0]).addCallback(get_response)
797802
return server.NOT_DONE_YET
798803
except Exception, e:
799804
request.write(json.dumps({"success": False, "reason": e.message}, indent=4))

db/datastore.py

+32-6
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,11 @@ def create_database(filepath=None):
6363
encryption_pubkey BLOB, subject TEXT, message_type TEXT, message TEXT, timestamp, INTEGER,
6464
avatar_hash BLOB, signature BLOB, outgoing INTEGER)''')
6565

66-
cursor.execute('''CREATE TABLE notifications(id TEXT PRIMARY KEY, guid BLOB, handle TEXT, message TEXT,
67-
timestamp INTEGER, avatar_hash BLOB, read INTEGER)''')
66+
cursor.execute('''CREATE TABLE notifications(id TEXT PRIMARY KEY, guid BLOB, handle TEXT, type TEXT,
67+
order_id TEXT, title TEXT, timestamp INTEGER, image_hash BLOB, read INTEGER)''')
68+
69+
cursor.execute('''CREATE TABLE broadcasts(id TEXT PRIMARY KEY, guid BLOB, handle TEXT, message TEXT,
70+
timestamp INTEGER, avatar_hash BLOB)''')
6871

6972
cursor.execute('''CREATE TABLE vendors(guid TEXT PRIMARY KEY, ip TEXT, port INTEGER, signedPubkey BLOB)''')
7073

@@ -359,15 +362,17 @@ def __init__(self):
359362
self.db = lite.connect(DATABASE)
360363
self.db.text_factory = str
361364

362-
def save_notification(self, notif_id, guid, handle, message, timestamp, avatar_hash):
365+
def save_notification(self, notif_id, guid, handle, notif_type, order_id, title, timestamp, image_hash):
363366
cursor = self.db.cursor()
364-
cursor.execute('''INSERT INTO notifications(id, guid, handle, message, timestamp, avatar_hash, read)
365-
VALUES (?,?,?,?,?,?,?)''', (notif_id, guid, handle, message, timestamp, avatar_hash, 0))
367+
cursor.execute('''INSERT INTO notifications(id, guid, handle, type, order_id, title, timestamp,
368+
image_hash, read) VALUES (?,?,?,?,?,?,?,?,?)''', (notif_id, guid, handle, notif_type, order_id, title, timestamp,
369+
image_hash, 0))
366370
self.db.commit()
367371

368372
def get_notifications(self):
369373
cursor = self.db.cursor()
370-
cursor.execute('''SELECT id, guid, handle, message, timestamp, avatar_hash, read FROM notifications''')
374+
cursor.execute('''SELECT id, guid, handle, type, order_id, title, timestamp, image_hash, read
375+
FROM notifications''')
371376
return cursor.fetchall()
372377

373378
def mark_as_read(self, notif_id):
@@ -380,6 +385,27 @@ def delete_notification(self, notif_id):
380385
cursor.execute('''DELETE FROM notifications WHERE id=?''', (notif_id,))
381386
self.db.commit()
382387

388+
class BroadcastStore(object):
389+
def __init__(self):
390+
self.db = lite.connect(DATABASE)
391+
self.db.text_factory = str
392+
393+
def save_broadcast(self, broadcast_id, guid, handle, message, timestamp, avatar_hash):
394+
cursor = self.db.cursor()
395+
cursor.execute('''INSERT INTO broadcasts(id, guid, handle, message, timestamp, avatar_hash)
396+
VALUES (?,?,?,?,?,?)''', (broadcast_id, guid, handle, message, timestamp, avatar_hash))
397+
self.db.commit()
398+
399+
def get_broadcasts(self):
400+
cursor = self.db.cursor()
401+
cursor.execute('''SELECT id, guid, handle, message, timestamp, avatar_hash FROM broadcasts''')
402+
return cursor.fetchall()
403+
404+
def delete_broadcast(self, broadcast_id):
405+
cursor = self.db.cursor()
406+
cursor.execute('''DELETE FROM broadcasts WHERE id=?''', (broadcast_id,))
407+
self.db.commit()
408+
383409
class VendorStore(object):
384410
def __init__(self):
385411
self.db = lite.connect(DATABASE)

db/tests/test_datastore.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -170,8 +170,8 @@ def test_saveMessage(self):
170170
def test_notificationStore(self):
171171
n = self.ns.get_notifications()
172172
self.assertTrue(len(n) == 0)
173-
self.ns.save_notification("1234", self.u.guid, self.m.handle, 'NOTICE',
174-
'0000-00-00 00:00:00', '')
173+
self.ns.save_notification("1234", self.u.guid, self.m.handle, 'NOTICE', "", ""
174+
'0000-00-00 00:00:00', '', 0)
175175
n = self.ns.get_notifications()
176176
self.assertIsNotNone(n)
177177
self.ns.delete_notification("1234")

dht/protocol.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,16 @@
44
"""
55

66
import random
7+
78
from twisted.internet import defer, reactor
89
from zope.interface import implements
910
import nacl.signing
11+
1012
from dht.node import Node
1113
from dht.routing import RoutingTable
1214
from dht.utils import digest
1315
from log import Logger
14-
from rpcudp import RPCProtocol
16+
from net.rpcudp import RPCProtocol
1517
from interfaces import MessageProcessor
1618
from protos import objects
1719
from protos.message import PING, STUN, STORE, DELETE, FIND_NODE, FIND_VALUE, HOLE_PUNCH

dht/tests/test_crawling.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@
77
from txrudp import packet, connection, rudp, constants
88
from twisted.internet import udp, address, task
99
from twisted.trial import unittest
10+
1011
from dht.crawling import RPCFindResponse, NodeSpiderCrawl, ValueSpiderCrawl
1112
from dht.node import Node, NodeHeap
1213
from dht.utils import digest
1314
from dht.storage import ForgetfulStorage
1415
from dht.protocol import KademliaProtocol
1516
from protos.objects import Value
16-
from wireprotocol import OpenBazaarProtocol
17+
from net.wireprotocol import OpenBazaarProtocol
1718
from db.datastore import Database
1819
from constants import ALPHA, KSIZE
1920

dht/tests/test_protocol.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,23 @@
22
import time
33
import random
44
from binascii import unhexlify
5-
65
import os
6+
77
import mock
88
import nacl.signing
99
import nacl.encoding
1010
import nacl.hash
1111
from txrudp import connection, rudp, packet, constants
1212
from twisted.trial import unittest
1313
from twisted.internet import task, address, udp, defer, reactor
14+
1415
from dht.protocol import KademliaProtocol
1516
from dht.utils import digest
1617
from dht.storage import ForgetfulStorage
1718
from dht.tests.utils import mknode
1819
from dht.node import Node
1920
from protos import message, objects
20-
from wireprotocol import OpenBazaarProtocol
21+
from net.wireprotocol import OpenBazaarProtocol
2122
from db import datastore
2223
from constants import PROTOCOL_VERSION
2324

interfaces.py

+27-4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from zope.interface import Interface, Attribute
44

5+
56
class MessageProcessor(Interface):
67
"""
78
This is an interface for processing messages coming off the wire. Classes that implement this interface should be
@@ -35,17 +36,19 @@ def __iter__():
3536
:return: iter([list of enums])
3637
"""
3738

38-
class NotificationListener(Interface):
39+
40+
class BroadcastListener(Interface):
3941
"""
40-
An interface for handling notifications sent to followers.
42+
An interface for handling broadcasts sent to followers.
4143
"""
4244

4345
def notify(guid, message):
4446
"""
45-
New notifications will be sent here. They will only show if this node is following the node
46-
which sent the notification.
47+
New broadcasts will be sent here. They will only show if this node is following the node
48+
which sent the broadcast.
4749
"""
4850

51+
4952
class MessageListener(Interface):
5053
"""
5154
An interface for handling messages sent between nodes.
@@ -57,4 +60,24 @@ def notify(plaintext_message, signature):
5760
Args:
5861
plaintext_message: the protobuf object containing the message
5962
signature: the signature covering the message.
63+
"""
64+
65+
66+
class NotificationListener(Interface):
67+
"""
68+
An interface for handling event notifications. New events should update this
69+
listener which will save the notifications to the db and push it to UI via websockets.
70+
"""
71+
72+
def notify(guid, handle, type, order_id, title, image_hash):
73+
"""
74+
This should be called to register a new notification.
75+
Args:
76+
guid: (in hex) optional depending on notification type.
77+
handle: optional depending on notification type.
78+
type: a `String` containing the type of notification,
79+
(ex: Follow, New Order, Order Confirmation, Payment Received).
80+
order_id: an order id if this notification is for an order
81+
title: a `String` which can be used for the item's title if an order notification.
82+
image_hash: optional depending on notification type.
6083
"""

0 commit comments

Comments
 (0)