and some untested `exact` and `flag` code also
This commit is contained in:
AF 2021-12-22 13:30:05 +03:00
parent 5f49cd7f46
commit da1d9a23d6
7 changed files with 46 additions and 19 deletions

View File

@ -1,2 +1,3 @@
# v25
replace public keys in `dev-config.json` and `staging-config.json` with your own to allow messaging

View File

@ -1,6 +1,6 @@
__all__ = ('Flags',)
import nacl.hash
Q_FLAG = '<?>'
__all__ = ('Flags',)
class Flags:
@ -9,14 +9,17 @@ class Flags:
def __init__(self, flags: str):
self.flags: str = flags
def quable(self) -> bool:
return Q_FLAG in self.flags
def hash(self):
return nacl.hash.sha256(self.flags.encode()).decode()
def deq(self) -> str:
return Flags(self.flags.replace(Q_FLAG, '')).deq() if self.quable() else self.flags
def joint(self, flags: str):
return flags.startswith(self.hash())
def enq(self) -> str:
return self.flags if self.quable() else self.flags + Q_FLAG
def join(self, flags: str):
h = self.hash()
if flags.startswith(h):
return flags
return h + flags
Flags.default = Flags('<unedited>').enq()
Flags.default = '<unedited>'

View File

@ -95,7 +95,7 @@ class Message:
def edit(self, pcontent: bytes) -> 'Message':
return Message(self.sfrom, self.sto, self.idnonce, None,
Encoding.nonce(), pcontent, None,
Flags(self.flags.replace('<unedited>', '<edited>')).enq()).sealed()
self.flags.replace('<unedited>', '<edited>')).sealed()
def edit_(self):
return self.flags_(self.flags)

View File

@ -258,30 +258,36 @@ class DBStorage(PushStorage):
),
))
query: Query = cquery
if 'ts' in params:
if '>' in params:
query = query.filter(Msg.ts > params['ts']['>'])
if '<' in params:
query = query.filter(Msg.ts < params['ts']['<'])
if params.get('before'):
query = query.filter(Msg.oid < cquery.filter(Msg.idn == Encoding.decode(params['before'])).one().oid)
if params.get('after'):
query = query.filter(Msg.oid > cquery.filter(Msg.idn == Encoding.decode(params['after'])).one().oid)
if params.get('exact'):
query = query.filter_by(idn=Encoding.decode(params['exact']))
query = query.filter_by(idn=Encoding.decode(params['exact']), sf=pair[0].vkey.encode())
for flag in params.get('flags', ()):
query = query.filter(Msg.flags.contains(flag))
query = query.order_by(Msg.oid.desc())
if 'limit' in params:
query = query.limit(params['limit'])
return map(Msg.to_message, list(query.from_self().order_by(Msg.oid)))
res = map(Msg.to_message, list(query.from_self().order_by(Msg.oid)))
if 'edit_' in params:
res = (m.edit_() for m in res)
return res
def exact(self, sfrom: Subject, sto: Subject, idnonce: bytes, editnonce: Optional[bytes]) -> Optional[Message]:
with closing(self.Session()) as session:
query: Query = session.query(Msg)
query = query.filter_by(sf=sfrom, st=sto, idn=idnonce)
if editnonce:
query = query.filter_by(en=editnonce)
msg: Optional[Msg] = query.one_or_none()
return msg or msg.to_message()
def flags(self, m: Message, flags: str):
assert not Flags(flags).quable(), 'flags misuse'
with closing(self.Session()) as session:
msg: Msg = self.one_alike(session, m)
assert msg.en == m.editnonce, 'flags misuse'
assert Flags(msg.flags).quable(), 'flags misuse'
assert Flags(msg.flags).joint(flags)
msg.flags = flags
session.commit()

View File

@ -33,6 +33,10 @@ class SecureStorage(PushStorage):
assert self.subject in pair, self.asrt()
return self.storage.pull(pair, params)
def exact(self, sfrom: Subject, sto: Subject, idnonce: bytes, editnonce: Optional[bytes]) -> Optional[Message]:
assert self.subject in (sfrom, sto)
return self.storage.exact(sfrom, sto, idnonce, editnonce)
def flags(self, m: Message, flags: str):
assert self.subject in m.pair, self.asrt()
return self.storage.flags(m, flags)

View File

@ -21,6 +21,9 @@ class AbstractStorage(ABC):
def pull(self, pair: Tuple[Subject, Subject], params: Optional[dict] = None) -> Iterable[Message]:
raise NotImplementedError
def exact(self, sfrom: Subject, sto: Subject, idnonce: bytes, editnonce: Optional[bytes]) -> Optional[Message]:
raise NotImplementedError
def flags(self, m: Message, flags: str):
raise NotImplementedError

View File

@ -42,6 +42,9 @@ class RemoteStorage(PushStorage):
return map(Message.loads,
self.req('pull', {'params': params, 'pair': [subject.dumps() for subject in pair]}))
def exact(self, sfrom: Subject, sto: Subject, idnonce: bytes, editnonce: Optional[bytes]) -> Optional[Message]:
raise NotImplementedError
def flags(self, m: Message, flags: str):
self.req('flags', {'m': m.dumps(), 'flags': flags})
@ -50,6 +53,13 @@ class RemoteStorage(PushStorage):
self.req('events', {'sfrom': sfrom.dumps(), 'sto': sto.dumps(),
'after': Encoding.encode(after)})]
def typing(self, sfrom: Subject, sto: Subject, last: float) -> float:
return self.req('typing', {
'sfrom': sfrom.dumps(),
'sto': sto.dumps(),
'last': last
})
def subscribe(self, subject: Subject, subscription: dict):
self.req('subscribe', {
'subject': subject.dumps(),