From 5a525316d813cba13f4583843c2d3da5ed273f45 Mon Sep 17 00:00:00 2001 From: Oleg Silkin Date: Mon, 20 May 2019 07:23:06 -0400 Subject: [PATCH] Adds asynchronous methods for writing to db --- lbry_comment_server/__init__.py | 8 ++-- lbry_comment_server/database.py | 65 +++++++++++++++++++++++++++++++-- lbry_comment_server/main.py | 2 +- tests/database_test.py | 4 +- 4 files changed, 69 insertions(+), 10 deletions(-) diff --git a/lbry_comment_server/__init__.py b/lbry_comment_server/__init__.py index 888dd4c..7df6fbc 100644 --- a/lbry_comment_server/__init__.py +++ b/lbry_comment_server/__init__.py @@ -2,8 +2,8 @@ from lbry_comment_server.settings import config from lbry_comment_server.database import obtain_connection, validate_input, get_claim_comments from lbry_comment_server.database import get_comments_by_id, get_comment_ids, create_comment from lbry_comment_server.handles import api_endpoint -schema = config['path']['schema'] -database_fp = config['path']['dev'] -backup = config['path']['backup'] -anonymous = config['anonymous'] +SCHEMA = config['path']['SCHEMA'] +DATABASE = config['path']['dev'] +BACKUP = config['path']['BACKUP'] +ANONYMOUS = config['ANONYMOUS'] diff --git a/lbry_comment_server/database.py b/lbry_comment_server/database.py index 998a8e8..687f357 100644 --- a/lbry_comment_server/database.py +++ b/lbry_comment_server/database.py @@ -1,13 +1,14 @@ import sqlite3 +import aiosqlite import typing import re import nacl.hash import time -from lbry_comment_server import anonymous, database_fp +from lbry_comment_server import ANONYMOUS, DATABASE def obtain_connection(filepath: str = None, row_factory: bool = True): - filepath = filepath if filepath else database_fp + filepath = filepath if filepath else DATABASE connection = sqlite3.connect(filepath) if row_factory: connection.row_factory = sqlite3.Row @@ -63,6 +64,8 @@ def _insert_channel(conn: sqlite3.Connection, channel_name: str, channel_id: str ) + + def _insert_comment(conn: sqlite3.Connection, claim_id: str = None, comment: str = None, channel_id: str = None, signature: str = None, parent_id: str = None) -> str: timestamp = time.time_ns() @@ -96,7 +99,7 @@ def create_comment(conn: sqlite3.Connection, comment: str, claim_id: str, **kwar except AssertionError: return None else: - channel_id = anonymous['channel_id'] + channel_id = ANONYMOUS['channel_id'] comment_id = _insert_comment( conn=conn, comment=comment, claim_id=claim_id, channel_id=channel_id, **kwargs ) @@ -140,6 +143,62 @@ def get_comments_by_id(conn, comment_ids: list) -> typing.Union[list, None]: )] +async def _insert_channel_async(db_file: str, channel_name: str, channel_id: str): + async with aiosqlite.connect(db_file) as db: + await db.execute('INSERT INTO CHANNEL(ClaimId, Name) VALUES (?, ?)', + (channel_id, channel_name)) + await db.commit() + + +async def _insert_comment_async(db_file: str, claim_id: str = None, comment: str = None, + channel_id: str = None, signature: str = None, parent_id: str = None) -> str: + timestamp = time.time_ns() + comment_prehash = ':'.join((claim_id, comment, str(timestamp),)) + comment_prehash = bytes(comment_prehash.encode('utf-8')) + comment_id = nacl.hash.sha256(comment_prehash).decode('utf-8') + async with aiosqlite.connect(db_file) as db: + await db.execute( + """ + INSERT INTO COMMENT(CommentId, LbryClaimId, ChannelId, Body, + ParentId, Signature, Timestamp) + VALUES (?, ?, ?, ?, ?, ?, ?) + """, + (comment_id, claim_id, channel_id, comment, parent_id, signature, timestamp) + ) + await db.commit() + return comment_id + + + +async def create_comment_async(db_file: str, comment: str, claim_id: str, **kwargs): + channel_id = kwargs.pop('channel_id', '') + channel_name = kwargs.pop('channel_name', '') + if channel_id or channel_name: + try: + validate_input( + comment=comment, + claim_id=claim_id, + channel_id=channel_id, + channel_name=channel_name, + ) + await _insert_channel_async(db_file, channel_name, channel_id) + except AssertionError: + return None + else: + channel_id = ANONYMOUS['channel_id'] + comment_id = await _insert_comment_async( + db_file=db_file, comment=comment, claim_id=claim_id, channel_id=channel_id, **kwargs + ) + async with await aiosqlite.connect(db_file) as db: + db.row_factory = aiosqlite.Row + curs = await db.execute( + 'SELECT * FROM COMMENTS_ON_CLAIMS WHERE comment_id = ?', (comment_id,) + ) + thing = await curs.fetchone() + await curs.close() + return dict(thing) if thing else None + + if __name__ == '__main__': pass # __generate_database_schema(connection, 'comments_ddl.sql') diff --git a/lbry_comment_server/main.py b/lbry_comment_server/main.py index 4027178..0cc9d50 100644 --- a/lbry_comment_server/main.py +++ b/lbry_comment_server/main.py @@ -4,7 +4,7 @@ import json from aiohttp import web from settings import config -from lbry_comment_server import database_fp +from lbry_comment_server import DATABASE from lbry_comment_server.database import obtain_connection diff --git a/tests/database_test.py b/tests/database_test.py index 26d433c..86580ca 100644 --- a/tests/database_test.py +++ b/tests/database_test.py @@ -80,7 +80,7 @@ class TestCommentCreation(DatabaseTestCase): comment = db.create_comment( conn=self.conn, claim_id=self.claimId, - comment='This is an anonymous comment' + comment='This is an ANONYMOUS comment' ) self.assertIsNotNone(comment) self.assertIn('comment', comment) @@ -163,7 +163,7 @@ class TestCommentCreation(DatabaseTestCase): claim_id=self.claimId, channel_name='', channel_id='529357c3422c6046d3fec76be2358001ba224b23', - comment='this username should not default to anonymous' + comment='this username should not default to ANONYMOUS' ) self.assertIsNone(comment) short_username = db.create_comment(