Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ flake8:
pip.install:
pip install -r requirements-dev.txt

docs.build:
sphinx-build docs/source/ docs/

docs.autodoc:
sphinx-apidoc -f -o docs/source .

#################################
###### DOCKER DEV COMMANDS ######
#################################
Expand Down
6 changes: 6 additions & 0 deletions db/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@


class ObserverNotRegisteredError(Exception):
"""
Exception responsible for missing Observer registry
"""
pass


class ObserverAlreadyRegisteredError(Exception):
"""
Exception responsible for duplicated Observer registry
"""
pass
63 changes: 61 additions & 2 deletions db/observer.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@


class ObserverMessage(Document):
"""MongoDB Document for a observer telegram sent message

Attributes:
message_id (int): telegram send message id
subject (Subject): subject reference
observer (Observer): observer reference
datetime: now() datetime
"""
message_id = IntField(required=True)
subject = ReferenceField('Subject', required=True)
observer = ReferenceField('Observer', required=True)
Expand All @@ -36,6 +44,13 @@ def __str__(self):


class Observer(Document):
"""MongoDB Document for official Telegram Channel

Attributes:
username (str): telegram chat username
chat_id (str): telegram chat id

"""
username = StringField(max_length=50)
chat_id = StringField(required=True, max_length=50, unique=True)

Expand All @@ -48,9 +63,23 @@ def __str__(self):
f"{self.chat_id}".strip()

def notify(self, update_message):
"""Notify observer of update message.

Calls:
>>> self._send_update_message(update_message)

Args:
update_message (UpdateMessage): update message to be notified

"""
self._send_update_message(update_message)

def _send_update_message(self, update_message):
"""Send update message to telegram chat and creates it's respective ObserverMessage

Args:
update_message (UpdateMessage): update message to be sent
"""
telegram_message = BotTelegramCore.send_message(
f'{update_message}', chat_id=self.chat_id)
ObserverMessage(
Expand All @@ -61,19 +90,46 @@ def _send_update_message(self, update_message):

@classmethod
def get_official_observer(cls):
"""get official observer from official chat_id

Returns:
Observer: official observer
"""
return cls.objects.get(chat_id=BotTelegramCore.instance().chat_id)


class UserObserver(Observer):
"""MongoDB Document for user's observer

Attributes:
username (str): telegram chat username
chat_id (str): telegram chat id
messages (list of ObserverMessage): list of ObserverMessage's
"""
messages = ListField(
ReferenceField(ObserverMessage, reverse_delete_rule=NULLIFY)
)

def notify(self, update_message):
"""Notify observer of update message.

Calls:
>>> self._remove_last_message_from_subject(update_message.subject)
>>> self._send_update_message(update_message)

Args:
update_message (UpdateMessage): update message to be notified

"""
self._remove_last_message_from_subject(update_message.subject)
self._send_update_message(update_message)

def _send_update_message(self, update_message):
"""Forward official channel update message to telegram chat and creates it's respective ObserverMessage

Args:
update_message (UpdateMessage): update message to be forwarded
"""
official_observer = Observer.get_official_observer()
last_official_message = ObserverMessage\
.objects(subject=update_message.subject,
Expand All @@ -93,6 +149,11 @@ def _send_update_message(self, update_message):
self.save()

def _remove_last_message_from_subject(self, subject):
"""Delete previous forwarded official channel update message from subject on telegram chat and removes it's respective ObserverMessage

Args:
subject (Subject): subject to be filter messages
"""
self.reload()
try:
observer_messages = filter(
Expand All @@ -113,5 +174,3 @@ def _remove_last_message_from_subject(self, subject):
pass
except BadRequest as e:
logger.warning(f'BadRequest {e}')
except Exception as e:
logger.error(e)
37 changes: 35 additions & 2 deletions db/subject.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@


class Subject(Document):
"""MongoDB Document for a split ticket VSP

Attributes:
emoji (str): A string emoji
name (str): name of split ticket VSP
uri (str): websocket URI
observers (list of UserObserver): observers watching this subject
"""

emoji = StringField(required=True, max_length=2)
name = StringField(required=True, max_length=55, unique=True)
uri = StringField(required=True, max_length=120, unique=True)
Expand All @@ -31,23 +40,47 @@ def __str__(self):

@property
def header(self):
"""str headear for subject

Returns:
str: emoji + name
"""
return f"{self.emoji} {self.name}"

def subscribe(self, observer):
"""Subscribe a Observer to this subject

Args:
observer (Observer): observer to subscribe
Raises:
ObserverAlreadyRegisteredError: if observer is already subscribed to subject
"""
if observer in self.observers:
raise ObserverAlreadyRegisteredError(f"Observer {observer} "
f"is already registered!")
f"is already subscribed!")
self.observers.append(observer)
self.save()

def unsubscribe(self, observer):
"""Unsubscribe a Observer to this subject

Args:
observer (Observer): observer to unsubscribe
Raises:
ObserverNotRegisteredError: if observer is not subscribed
"""
if observer not in self.observers:
raise ObserverNotRegisteredError(f"Observer {observer} "
f"is not registered!")
f"is not subscribed!")
self.observers.remove(observer)
self.save()

def notify(self, update_message):
"""Notify official Observer and UserObserver's subscribed of some UpdateMessage

Args:
update_message (UpdateMessage): update message to be notified
"""
official_observer = Observer.get_official_observer()
logger.info(f'Notifying official observer {official_observer} '
f'for {self}')
Expand Down
53 changes: 53 additions & 0 deletions db/update_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@


class Amount(EmbeddedDocument):
"""MongoDB EmbeddedDocument for some amount value in ATOM

Attributes:
_value (int): atom value
"""
ATOM_DECIMALS = 100000000

_value = IntField(required=True)
Expand All @@ -19,6 +24,17 @@ def __str__(self):

@property
def value(self):
"""Value get property method

Returns:
float: the value of amount in DCR

Args:
value: desired value

Raises:
TypeError: if value is not int
"""
return self._value/self.ATOM_DECIMALS

@value.setter
Expand All @@ -29,6 +45,12 @@ def value(self, value: int):


class Session(EmbeddedDocument):
"""MongoDB EmbeddedDocument for a session data

Attributes:
hash (str): session id
amounts (list of Amount): list of Amount's in session
"""
hash = StringField(required=True)
amounts = EmbeddedDocumentListField(Amount, required=True)

Expand All @@ -44,13 +66,31 @@ def __str__(self):

@classmethod
def from_data(cls, data):
"""Create a session from a data

Examples:
>>> session = Session.from_data({'name': 'some_hash', 'amounts': [1000000000, 200000000]})

Args:
data: data to create a Session and it's respective Amount's

Returns:
Session: Session created
"""
instance = cls(data.get('name'))
for amount in data.get('amounts'):
instance.amounts.append(Amount(amount))
return instance


class UpdateMessage(Document):
"""MongoDB Document for a update message

Attributes:
subject (Subject): subject of this update message
sessions (list of Session): list of sessions
datetime: now() datetime
"""
subject = ReferenceField(Subject, required=True)
sessions = EmbeddedDocumentListField(Session, required=True)
datetime = DateTimeField(default=pendulum.now, required=True)
Expand All @@ -64,6 +104,19 @@ def __str__(self):

@classmethod
def from_data(cls, subject, msg):
"""Create a update message from a data

Examples:
>>> subject = Subject()
>>> update_message = UpdateMessage.from_data(subject, [{'name': 'some_hash', 'amounts': [1000000000, 200000000]}])

Args:
msg: msg received from websocket to create a UpdateMessage and it's respective Session's
subject Subject: Subject for UpdateMessage

Returns:
UpdateMessage: UpdateMessage created
"""
json_data = loads(msg)
instance = cls(subject=subject)
for data in json_data:
Expand Down
Empty file added docs/.nojekyll
Empty file.
20 changes: 20 additions & 0 deletions docs/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Minimal makefile for Sphinx documentation
#

# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = source
BUILDDIR = build

# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

.PHONY: help Makefile

# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
35 changes: 35 additions & 0 deletions docs/make.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
@ECHO OFF

pushd %~dp0

REM Command file for Sphinx documentation

if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=source
set BUILDDIR=build

if "%1" == "" goto help

%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)

%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end

:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%

:end
popd
Loading