connection = \OC::$server->getDatabaseConnection(); $this->rootFolder = $this->createMock(IRootFolder::class); $sql = $this->connection->getDatabasePlatform()->getTruncateTableSQL('`*PREFIX*comments`'); $this->connection->prepare($sql)->execute(); $sql = $this->connection->getDatabasePlatform()->getTruncateTableSQL('`*PREFIX*reactions`'); $this->connection->prepare($sql)->execute(); } protected function addDatabaseEntry($parentId, $topmostParentId, $creationDT = null, $latestChildDT = null, $objectId = null, $expireDate = null) { if (is_null($creationDT)) { $creationDT = new \DateTime(); } if (is_null($latestChildDT)) { $latestChildDT = new \DateTime('yesterday'); } if (is_null($objectId)) { $objectId = 'file64'; } $qb = $this->connection->getQueryBuilder(); $qb ->insert('comments') ->values([ 'parent_id' => $qb->createNamedParameter($parentId), 'topmost_parent_id' => $qb->createNamedParameter($topmostParentId), 'children_count' => $qb->createNamedParameter(2), 'actor_type' => $qb->createNamedParameter('users'), 'actor_id' => $qb->createNamedParameter('alice'), 'message' => $qb->createNamedParameter('nice one'), 'verb' => $qb->createNamedParameter('comment'), 'creation_timestamp' => $qb->createNamedParameter($creationDT, IQueryBuilder::PARAM_DATETIME_MUTABLE), 'latest_child_timestamp' => $qb->createNamedParameter($latestChildDT, IQueryBuilder::PARAM_DATETIME_MUTABLE), 'object_type' => $qb->createNamedParameter('files'), 'object_id' => $qb->createNamedParameter($objectId), 'expire_date' => $qb->createNamedParameter($expireDate, IQueryBuilder::PARAM_DATETIME_MUTABLE), 'reference_id' => $qb->createNamedParameter('referenceId'), 'meta_data' => $qb->createNamedParameter(json_encode(['last_edit_actor_id' => 'admin'])), ]) ->execute(); return $qb->getLastInsertId(); } protected function getManager() { return new Manager( $this->connection, $this->createMock(LoggerInterface::class), $this->createMock(IConfig::class), $this->createMock(ITimeFactory::class), new EmojiHelper($this->connection), $this->createMock(IInitialStateService::class), $this->rootFolder, $this->createMock(IEventDispatcher::class), ); } public function testGetCommentNotFound(): void { $this->expectException(\OCP\Comments\NotFoundException::class); $manager = $this->getManager(); $manager->get('22'); } public function testGetCommentNotFoundInvalidInput(): void { $this->expectException(\InvalidArgumentException::class); $manager = $this->getManager(); $manager->get('unexisting22'); } public function testGetComment(): void { $manager = $this->getManager(); $creationDT = new \DateTime(); $latestChildDT = new \DateTime('yesterday'); $qb = \OC::$server->getDatabaseConnection()->getQueryBuilder(); $qb ->insert('comments') ->values([ 'parent_id' => $qb->createNamedParameter('2'), 'topmost_parent_id' => $qb->createNamedParameter('1'), 'children_count' => $qb->createNamedParameter(2), 'actor_type' => $qb->createNamedParameter('users'), 'actor_id' => $qb->createNamedParameter('alice'), 'message' => $qb->createNamedParameter('nice one'), 'verb' => $qb->createNamedParameter('comment'), 'creation_timestamp' => $qb->createNamedParameter($creationDT, 'datetime'), 'latest_child_timestamp' => $qb->createNamedParameter($latestChildDT, 'datetime'), 'object_type' => $qb->createNamedParameter('files'), 'object_id' => $qb->createNamedParameter('file64'), 'reference_id' => $qb->createNamedParameter('referenceId'), 'meta_data' => $qb->createNamedParameter(json_encode(['last_edit_actor_id' => 'admin'])), ]) ->execute(); $id = strval($qb->getLastInsertId()); $comment = $manager->get($id); $this->assertTrue($comment instanceof IComment); $this->assertSame($comment->getId(), $id); $this->assertSame($comment->getParentId(), '2'); $this->assertSame($comment->getTopmostParentId(), '1'); $this->assertSame($comment->getChildrenCount(), 2); $this->assertSame($comment->getActorType(), 'users'); $this->assertSame($comment->getActorId(), 'alice'); $this->assertSame($comment->getMessage(), 'nice one'); $this->assertSame($comment->getVerb(), 'comment'); $this->assertSame($comment->getObjectType(), 'files'); $this->assertSame($comment->getObjectId(), 'file64'); $this->assertEquals($comment->getCreationDateTime()->getTimestamp(), $creationDT->getTimestamp()); $this->assertEquals($comment->getLatestChildDateTime(), $latestChildDT); $this->assertEquals($comment->getReferenceId(), 'referenceId'); $this->assertEquals($comment->getMetaData(), ['last_edit_actor_id' => 'admin']); } public function testGetTreeNotFound(): void { $this->expectException(\OCP\Comments\NotFoundException::class); $manager = $this->getManager(); $manager->getTree('22'); } public function testGetTreeNotFoundInvalidIpnut(): void { $this->expectException(\InvalidArgumentException::class); $manager = $this->getManager(); $manager->getTree('unexisting22'); } public function testGetTree(): void { $headId = $this->addDatabaseEntry(0, 0); $this->addDatabaseEntry($headId, $headId, new \DateTime('-3 hours')); $this->addDatabaseEntry($headId, $headId, new \DateTime('-2 hours')); $id = $this->addDatabaseEntry($headId, $headId, new \DateTime('-1 hour')); $manager = $this->getManager(); $tree = $manager->getTree($headId); // Verifying the root comment $this->assertTrue(isset($tree['comment'])); $this->assertTrue($tree['comment'] instanceof IComment); $this->assertSame($tree['comment']->getId(), strval($headId)); $this->assertTrue(isset($tree['replies'])); $this->assertSame(count($tree['replies']), 3); // one level deep foreach ($tree['replies'] as $reply) { $this->assertTrue($reply['comment'] instanceof IComment); $this->assertSame($reply['comment']->getId(), strval($id)); $this->assertSame(count($reply['replies']), 0); $id--; } } public function testGetTreeNoReplies(): void { $id = $this->addDatabaseEntry(0, 0); $manager = $this->getManager(); $tree = $manager->getTree($id); // Verifying the root comment $this->assertTrue(isset($tree['comment'])); $this->assertTrue($tree['comment'] instanceof IComment); $this->assertSame($tree['comment']->getId(), strval($id)); $this->assertTrue(isset($tree['replies'])); $this->assertSame(count($tree['replies']), 0); // one level deep foreach ($tree['replies'] as $reply) { throw new \Exception('This ain`t happen'); } } public function testGetTreeWithLimitAndOffset(): void { $headId = $this->addDatabaseEntry(0, 0); $this->addDatabaseEntry($headId, $headId, new \DateTime('-3 hours')); $this->addDatabaseEntry($headId, $headId, new \DateTime('-2 hours')); $this->addDatabaseEntry($headId, $headId, new \DateTime('-1 hour')); $idToVerify = $this->addDatabaseEntry($headId, $headId, new \DateTime()); $manager = $this->getManager(); for ($offset = 0; $offset < 3; $offset += 2) { $tree = $manager->getTree(strval($headId), 2, $offset); // Verifying the root comment $this->assertTrue(isset($tree['comment'])); $this->assertTrue($tree['comment'] instanceof IComment); $this->assertSame($tree['comment']->getId(), strval($headId)); $this->assertTrue(isset($tree['replies'])); $this->assertSame(count($tree['replies']), 2); // one level deep foreach ($tree['replies'] as $reply) { $this->assertTrue($reply['comment'] instanceof IComment); $this->assertSame($reply['comment']->getId(), strval($idToVerify)); $this->assertSame(count($reply['replies']), 0); $idToVerify--; } } } public function testGetForObject(): void { $this->addDatabaseEntry(0, 0); $manager = $this->getManager(); $comments = $manager->getForObject('files', 'file64'); $this->assertTrue(is_array($comments)); $this->assertSame(count($comments), 1); $this->assertTrue($comments[0] instanceof IComment); $this->assertSame($comments[0]->getMessage(), 'nice one'); } public function testGetForObjectWithLimitAndOffset(): void { $this->addDatabaseEntry(0, 0, new \DateTime('-6 hours')); $this->addDatabaseEntry(0, 0, new \DateTime('-5 hours')); $this->addDatabaseEntry(1, 1, new \DateTime('-4 hours')); $this->addDatabaseEntry(0, 0, new \DateTime('-3 hours')); $this->addDatabaseEntry(2, 2, new \DateTime('-2 hours')); $this->addDatabaseEntry(2, 2, new \DateTime('-1 hours')); $idToVerify = $this->addDatabaseEntry(3, 1, new \DateTime()); $manager = $this->getManager(); $offset = 0; do { $comments = $manager->getForObject('files', 'file64', 3, $offset); $this->assertTrue(is_array($comments)); foreach ($comments as $comment) { $this->assertTrue($comment instanceof IComment); $this->assertSame($comment->getMessage(), 'nice one'); $this->assertSame($comment->getId(), strval($idToVerify)); $idToVerify--; } $offset += 3; } while (count($comments) > 0); } public function testGetForObjectWithDateTimeConstraint(): void { $this->addDatabaseEntry(0, 0, new \DateTime('-6 hours')); $this->addDatabaseEntry(0, 0, new \DateTime('-5 hours')); $id1 = $this->addDatabaseEntry(0, 0, new \DateTime('-3 hours')); $id2 = $this->addDatabaseEntry(2, 2, new \DateTime('-2 hours')); $manager = $this->getManager(); $comments = $manager->getForObject('files', 'file64', 0, 0, new \DateTime('-4 hours')); $this->assertSame(count($comments), 2); $this->assertSame($comments[0]->getId(), strval($id2)); $this->assertSame($comments[1]->getId(), strval($id1)); } public function testGetForObjectWithLimitAndOffsetAndDateTimeConstraint(): void { $this->addDatabaseEntry(0, 0, new \DateTime('-7 hours')); $this->addDatabaseEntry(0, 0, new \DateTime('-6 hours')); $this->addDatabaseEntry(1, 1, new \DateTime('-5 hours')); $this->addDatabaseEntry(0, 0, new \DateTime('-3 hours')); $this->addDatabaseEntry(2, 2, new \DateTime('-2 hours')); $this->addDatabaseEntry(2, 2, new \DateTime('-1 hours')); $idToVerify = $this->addDatabaseEntry(3, 1, new \DateTime()); $manager = $this->getManager(); $offset = 0; do { $comments = $manager->getForObject('files', 'file64', 3, $offset, new \DateTime('-4 hours')); $this->assertTrue(is_array($comments)); foreach ($comments as $comment) { $this->assertTrue($comment instanceof IComment); $this->assertSame($comment->getMessage(), 'nice one'); $this->assertSame($comment->getId(), strval($idToVerify)); $this->assertTrue(intval($comment->getId()) >= 4); $idToVerify--; } $offset += 3; } while (count($comments) > 0); } public function testGetNumberOfCommentsForObject(): void { for ($i = 1; $i < 5; $i++) { $this->addDatabaseEntry(0, 0); } $manager = $this->getManager(); $amount = $manager->getNumberOfCommentsForObject('untype', '00'); $this->assertSame($amount, 0); $amount = $manager->getNumberOfCommentsForObject('files', 'file64'); $this->assertSame($amount, 4); } public function testGetNumberOfUnreadCommentsForFolder(): void { $folder = $this->createMock(Folder::class); $fileIds = range(1111, 1114); $children = array_map(function (int $id) { $file = $this->createMock(Folder::class); $file->method('getId') ->willReturn($id); return $file; }, $fileIds); $folder->method('getId')->willReturn(1000); $folder->method('getDirectoryListing')->willReturn($children); $this->rootFolder->method('getFirstNodeById') ->with($folder->getId()) ->willReturn($folder); // 2 comment for 1111 with 1 before read marker // 2 comments for 1112 with no read marker // 1 comment for 1113 before read marker // 1 comment for 1114 with no read marker $this->addDatabaseEntry(0, 0, null, null, $fileIds[1]); for ($i = 0; $i < 4; $i++) { $this->addDatabaseEntry(0, 0, null, null, $fileIds[$i]); } $this->addDatabaseEntry(0, 0, (new \DateTime())->modify('-2 days'), null, $fileIds[0]); /** @var IUser|\PHPUnit\Framework\MockObject\MockObject $user */ $user = $this->createMock(IUser::class); $user->expects($this->any()) ->method('getUID') ->willReturn('comment_test'); $manager = $this->getManager(); $manager->setReadMark('files', (string)$fileIds[0], (new \DateTime())->modify('-1 days'), $user); $manager->setReadMark('files', (string)$fileIds[2], (new \DateTime()), $user); $amount = $manager->getNumberOfUnreadCommentsForFolder($folder->getId(), $user); $this->assertEquals([ $fileIds[0] => 1, $fileIds[1] => 2, $fileIds[3] => 1, ], $amount); } /** * @dataProvider dataGetForObjectSince * @param $lastKnown * @param $order * @param $limit * @param $resultFrom * @param $resultTo */ public function testGetForObjectSince($lastKnown, $order, $limit, $resultFrom, $resultTo): void { $ids = []; $ids[] = $this->addDatabaseEntry(0, 0); $ids[] = $this->addDatabaseEntry(0, 0); $ids[] = $this->addDatabaseEntry(0, 0); $ids[] = $this->addDatabaseEntry(0, 0); $ids[] = $this->addDatabaseEntry(0, 0); $manager = $this->getManager(); $comments = $manager->getForObjectSince('files', 'file64', ($lastKnown === null ? 0 : $ids[$lastKnown]), $order, $limit); $expected = array_slice($ids, $resultFrom, $resultTo - $resultFrom + 1); if ($order === 'desc') { $expected = array_reverse($expected); } $this->assertSame($expected, array_map(function (IComment $c) { return (int)$c->getId(); }, $comments)); } public function dataGetForObjectSince() { return [ [null, 'asc', 20, 0, 4], [null, 'asc', 2, 0, 1], [null, 'desc', 20, 0, 4], [null, 'desc', 2, 3, 4], [1, 'asc', 20, 2, 4], [1, 'asc', 2, 2, 3], [3, 'desc', 20, 0, 2], [3, 'desc', 2, 1, 2], ]; } public function invalidCreateArgsProvider() { return [ ['', 'aId-1', 'oType-1', 'oId-1'], ['aType-1', '', 'oType-1', 'oId-1'], ['aType-1', 'aId-1', '', 'oId-1'], ['aType-1', 'aId-1', 'oType-1', ''], [1, 'aId-1', 'oType-1', 'oId-1'], ['aType-1', 1, 'oType-1', 'oId-1'], ['aType-1', 'aId-1', 1, 'oId-1'], ['aType-1', 'aId-1', 'oType-1', 1], ]; } /** * @dataProvider invalidCreateArgsProvider * @param string $aType * @param string $aId * @param string $oType * @param string $oId */ public function testCreateCommentInvalidArguments($aType, $aId, $oType, $oId): void { $this->expectException(\InvalidArgumentException::class); $manager = $this->getManager(); $manager->create($aType, $aId, $oType, $oId); } public function testCreateComment(): void { $actorType = 'bot'; $actorId = 'bob'; $objectType = 'weather'; $objectId = 'bielefeld'; $comment = $this->getManager()->create($actorType, $actorId, $objectType, $objectId); $this->assertTrue($comment instanceof IComment); $this->assertSame($comment->getActorType(), $actorType); $this->assertSame($comment->getActorId(), $actorId); $this->assertSame($comment->getObjectType(), $objectType); $this->assertSame($comment->getObjectId(), $objectId); } public function testDelete(): void { $this->expectException(\OCP\Comments\NotFoundException::class); $manager = $this->getManager(); $done = $manager->delete('404'); $this->assertFalse($done); $done = $manager->delete('%'); $this->assertFalse($done); $done = $manager->delete(''); $this->assertFalse($done); $id = strval($this->addDatabaseEntry(0, 0)); $comment = $manager->get($id); $this->assertTrue($comment instanceof IComment); $done = $manager->delete($id); $this->assertTrue($done); $manager->get($id); } /** * @dataProvider providerTestSave */ public function testSave(string $message, string $actorId, string $verb, ?string $parentId, ?string $id = ''): IComment { $manager = $this->getManager(); $comment = new Comment(); $comment ->setId($id) ->setActor('users', $actorId) ->setObject('files', 'file64') ->setMessage($message) ->setVerb($verb); if ($parentId) { $comment->setParentId($parentId); } $saveSuccessful = $manager->save($comment); $this->assertTrue($saveSuccessful); $this->assertTrue($comment->getId() !== ''); $this->assertTrue($comment->getId() !== '0'); $this->assertTrue(!is_null($comment->getCreationDateTime())); $loadedComment = $manager->get($comment->getId()); $this->assertSame($comment->getMessage(), $loadedComment->getMessage()); $this->assertEquals($comment->getCreationDateTime()->getTimestamp(), $loadedComment->getCreationDateTime()->getTimestamp()); return $comment; } public function providerTestSave(): array { return [ ['very beautiful, I am impressed!', 'alice', 'comment', null] ]; } public function testSaveUpdate(): void { $manager = $this->getManager(); $comment = new Comment(); $comment ->setActor('users', 'alice') ->setObject('files', 'file64') ->setMessage('very beautiful, I am impressed!') ->setVerb('comment') ->setExpireDate(new \DateTime('+2 hours')); $manager->save($comment); $loadedComment = $manager->get($comment->getId()); // Compare current object with database values $this->assertSame($comment->getMessage(), $loadedComment->getMessage()); $this->assertSame( $comment->getExpireDate()->format('Y-m-d H:i:s'), $loadedComment->getExpireDate()->format('Y-m-d H:i:s') ); // Preserve the original comment to compare after update $original = clone $comment; // Update values $comment->setMessage('very beautiful, I am really so much impressed!') ->setExpireDate(new \DateTime('+1 hours')); $manager->save($comment); $loadedComment = $manager->get($comment->getId()); // Compare current object with database values $this->assertSame($comment->getMessage(), $loadedComment->getMessage()); $this->assertSame( $comment->getExpireDate()->format('Y-m-d H:i:s'), $loadedComment->getExpireDate()->format('Y-m-d H:i:s') ); // Compare original object with database values $this->assertNotSame($original->getMessage(), $loadedComment->getMessage()); $this->assertNotSame( $original->getExpireDate()->format('Y-m-d H:i:s'), $loadedComment->getExpireDate()->format('Y-m-d H:i:s') ); } public function testSaveUpdateException(): void { $this->expectException(\OCP\Comments\NotFoundException::class); $manager = $this->getManager(); $comment = new Comment(); $comment ->setActor('users', 'alice') ->setObject('files', 'file64') ->setMessage('very beautiful, I am impressed!') ->setVerb('comment'); $manager->save($comment); $manager->delete($comment->getId()); $comment->setMessage('very beautiful, I am really so much impressed!'); $manager->save($comment); } public function testSaveIncomplete(): void { $this->expectException(\UnexpectedValueException::class); $manager = $this->getManager(); $comment = new Comment(); $comment->setMessage('from no one to nothing'); $manager->save($comment); } public function testSaveAsChild(): void { $id = $this->addDatabaseEntry(0, 0); $manager = $this->getManager(); for ($i = 0; $i < 3; $i++) { $comment = new Comment(); $comment ->setActor('users', 'alice') ->setObject('files', 'file64') ->setParentId(strval($id)) ->setMessage('full ack') ->setVerb('comment') // setting the creation time avoids using sleep() while making sure to test with different timestamps ->setCreationDateTime(new \DateTime('+' . $i . ' minutes')); $manager->save($comment); $this->assertSame($comment->getTopmostParentId(), strval($id)); $parentComment = $manager->get(strval($id)); $this->assertSame($parentComment->getChildrenCount(), $i + 1); $this->assertEquals($parentComment->getLatestChildDateTime()->getTimestamp(), $comment->getCreationDateTime()->getTimestamp()); } } public function invalidActorArgsProvider() { return [ ['', ''], [1, 'alice'], ['users', 1], ]; } /** * @dataProvider invalidActorArgsProvider * @param string $type * @param string $id */ public function testDeleteReferencesOfActorInvalidInput($type, $id): void { $this->expectException(\InvalidArgumentException::class); $manager = $this->getManager(); $manager->deleteReferencesOfActor($type, $id); } public function testDeleteReferencesOfActor(): void { $ids = []; $ids[] = $this->addDatabaseEntry(0, 0); $ids[] = $this->addDatabaseEntry(0, 0); $ids[] = $this->addDatabaseEntry(0, 0); $manager = $this->getManager(); // just to make sure they are really set, with correct actor data $comment = $manager->get(strval($ids[1])); $this->assertSame($comment->getActorType(), 'users'); $this->assertSame($comment->getActorId(), 'alice'); $wasSuccessful = $manager->deleteReferencesOfActor('users', 'alice'); $this->assertTrue($wasSuccessful); foreach ($ids as $id) { $comment = $manager->get(strval($id)); $this->assertSame($comment->getActorType(), ICommentsManager::DELETED_USER); $this->assertSame($comment->getActorId(), ICommentsManager::DELETED_USER); } // actor info is gone from DB, but when database interaction is alright, // we still expect to get true back $wasSuccessful = $manager->deleteReferencesOfActor('users', 'alice'); $this->assertTrue($wasSuccessful); } public function testDeleteReferencesOfActorWithUserManagement(): void { $user = \OC::$server->getUserManager()->createUser('xenia', 'NotAnEasyPassword123456+'); $this->assertTrue($user instanceof IUser); $manager = \OC::$server->get(ICommentsManager::class); $comment = $manager->create('users', $user->getUID(), 'files', 'file64'); $comment ->setMessage('Most important comment I ever left on the Internet.') ->setVerb('comment'); $status = $manager->save($comment); $this->assertTrue($status); $commentID = $comment->getId(); $user->delete(); $comment = $manager->get($commentID); $this->assertSame($comment->getActorType(), ICommentsManager::DELETED_USER); $this->assertSame($comment->getActorId(), ICommentsManager::DELETED_USER); } public function invalidObjectArgsProvider() { return [ ['', ''], [1, 'file64'], ['files', 1], ]; } /** * @dataProvider invalidObjectArgsProvider * @param string $type * @param string $id */ public function testDeleteCommentsAtObjectInvalidInput($type, $id): void { $this->expectException(\InvalidArgumentException::class); $manager = $this->getManager(); $manager->deleteCommentsAtObject($type, $id); } public function testDeleteCommentsAtObject(): void { $ids = []; $ids[] = $this->addDatabaseEntry(0, 0); $ids[] = $this->addDatabaseEntry(0, 0); $ids[] = $this->addDatabaseEntry(0, 0); $manager = $this->getManager(); // just to make sure they are really set, with correct actor data $comment = $manager->get(strval($ids[1])); $this->assertSame($comment->getObjectType(), 'files'); $this->assertSame($comment->getObjectId(), 'file64'); $wasSuccessful = $manager->deleteCommentsAtObject('files', 'file64'); $this->assertTrue($wasSuccessful); $verified = 0; foreach ($ids as $id) { try { $manager->get(strval($id)); } catch (NotFoundException $e) { $verified++; } } $this->assertSame($verified, 3); // actor info is gone from DB, but when database interaction is alright, // we still expect to get true back $wasSuccessful = $manager->deleteCommentsAtObject('files', 'file64'); $this->assertTrue($wasSuccessful); } public function testDeleteCommentsExpiredAtObjectTypeAndId(): void { $ids = []; $ids[] = $this->addDatabaseEntry(0, 0, null, null, null, new \DateTime('+2 hours')); $ids[] = $this->addDatabaseEntry(0, 0, null, null, null, new \DateTime('+2 hours')); $ids[] = $this->addDatabaseEntry(0, 0, null, null, null, new \DateTime('+2 hours')); $ids[] = $this->addDatabaseEntry(0, 0, null, null, null, new \DateTime('-2 hours')); $ids[] = $this->addDatabaseEntry(0, 0, null, null, null, new \DateTime('-2 hours')); $ids[] = $this->addDatabaseEntry(0, 0, null, null, null, new \DateTime('-2 hours')); $manager = new Manager( $this->connection, $this->createMock(LoggerInterface::class), $this->createMock(IConfig::class), Server::get(ITimeFactory::class), new EmojiHelper($this->connection), $this->createMock(IInitialStateService::class), $this->rootFolder, $this->createMock(IEventDispatcher::class) ); // just to make sure they are really set, with correct actor data $comment = $manager->get((string)$ids[1]); $this->assertSame($comment->getObjectType(), 'files'); $this->assertSame($comment->getObjectId(), 'file64'); $deleted = $manager->deleteCommentsExpiredAtObject('files', 'file64'); $this->assertTrue($deleted); $deleted = 0; $exists = 0; foreach ($ids as $id) { try { $manager->get((string)$id); $exists++; } catch (NotFoundException $e) { $deleted++; } } $this->assertSame($exists, 3); $this->assertSame($deleted, 3); // actor info is gone from DB, but when database interaction is alright, // we still expect to get true back $deleted = $manager->deleteCommentsExpiredAtObject('files', 'file64'); $this->assertFalse($deleted); } public function testDeleteCommentsExpiredAtObjectType(): void { $ids = []; $ids[] = $this->addDatabaseEntry(0, 0, null, null, 'file1', new \DateTime('-2 hours')); $ids[] = $this->addDatabaseEntry(0, 0, null, null, 'file2', new \DateTime('-2 hours')); $ids[] = $this->addDatabaseEntry(0, 0, null, null, 'file3', new \DateTime('-2 hours')); $ids[] = $this->addDatabaseEntry(0, 0, null, null, 'file3', new \DateTime()); $ids[] = $this->addDatabaseEntry(0, 0, null, null, 'file3', new \DateTime()); $ids[] = $this->addDatabaseEntry(0, 0, null, null, 'file3', new \DateTime()); $manager = new Manager( $this->connection, $this->createMock(LoggerInterface::class), $this->createMock(IConfig::class), Server::get(ITimeFactory::class), new EmojiHelper($this->connection), $this->createMock(IInitialStateService::class), $this->rootFolder, $this->createMock(IEventDispatcher::class) ); $deleted = $manager->deleteCommentsExpiredAtObject('files'); $this->assertTrue($deleted); $deleted = 0; $exists = 0; foreach ($ids as $id) { try { $manager->get((string)$id); $exists++; } catch (NotFoundException $e) { $deleted++; } } $this->assertSame($exists, 0); $this->assertSame($deleted, 6); // actor info is gone from DB, but when database interaction is alright, // we still expect to get true back $deleted = $manager->deleteCommentsExpiredAtObject('files'); $this->assertFalse($deleted); } public function testSetMarkRead(): void { /** @var IUser|\PHPUnit\Framework\MockObject\MockObject $user */ $user = $this->createMock(IUser::class); $user->expects($this->any()) ->method('getUID') ->willReturn('alice'); $dateTimeSet = new \DateTime(); $manager = $this->getManager(); $manager->setReadMark('robot', '36', $dateTimeSet, $user); $dateTimeGet = $manager->getReadMark('robot', '36', $user); $this->assertEquals($dateTimeGet->getTimestamp(), $dateTimeSet->getTimestamp()); } public function testSetMarkReadUpdate(): void { /** @var IUser|\PHPUnit\Framework\MockObject\MockObject $user */ $user = $this->createMock(IUser::class); $user->expects($this->any()) ->method('getUID') ->willReturn('alice'); $dateTimeSet = new \DateTime('yesterday'); $manager = $this->getManager(); $manager->setReadMark('robot', '36', $dateTimeSet, $user); $dateTimeSet = new \DateTime('today'); $manager->setReadMark('robot', '36', $dateTimeSet, $user); $dateTimeGet = $manager->getReadMark('robot', '36', $user); $this->assertEquals($dateTimeGet, $dateTimeSet); } public function testReadMarkDeleteUser(): void { /** @var IUser|\PHPUnit\Framework\MockObject\MockObject $user */ $user = $this->createMock(IUser::class); $user->expects($this->any()) ->method('getUID') ->willReturn('alice'); $dateTimeSet = new \DateTime(); $manager = $this->getManager(); $manager->setReadMark('robot', '36', $dateTimeSet, $user); $manager->deleteReadMarksFromUser($user); $dateTimeGet = $manager->getReadMark('robot', '36', $user); $this->assertNull($dateTimeGet); } public function testReadMarkDeleteObject(): void { /** @var IUser|\PHPUnit\Framework\MockObject\MockObject $user */ $user = $this->createMock(IUser::class); $user->expects($this->any()) ->method('getUID') ->willReturn('alice'); $dateTimeSet = new \DateTime(); $manager = $this->getManager(); $manager->setReadMark('robot', '36', $dateTimeSet, $user); $manager->deleteReadMarksOnObject('robot', '36'); $dateTimeGet = $manager->getReadMark('robot', '36', $user); $this->assertNull($dateTimeGet); } public function testSendEvent(): void { $handler1 = $this->getMockBuilder(ICommentsEventHandler::class)->getMock(); $handler1->expects($this->exactly(4)) ->method('handle'); $handler2 = $this->getMockBuilder(ICommentsEventHandler::class)->getMock(); $handler1->expects($this->exactly(4)) ->method('handle'); $manager = $this->getManager(); $manager->registerEventHandler(function () use ($handler1) { return $handler1; }); $manager->registerEventHandler(function () use ($handler2) { return $handler2; }); $comment = new Comment(); $comment ->setActor('users', 'alice') ->setObject('files', 'file64') ->setMessage('very beautiful, I am impressed!') ->setVerb('comment'); // Add event $manager->save($comment); // Update event $comment->setMessage('Different topic'); $manager->save($comment); // Delete event $manager->delete($comment->getId()); } public function testResolveDisplayName(): void { $manager = $this->getManager(); $planetClosure = function ($name) { return ucfirst($name); }; $galaxyClosure = function ($name) { return strtoupper($name); }; $manager->registerDisplayNameResolver('planet', $planetClosure); $manager->registerDisplayNameResolver('galaxy', $galaxyClosure); $this->assertSame('Neptune', $manager->resolveDisplayName('planet', 'neptune')); $this->assertSame('SOMBRERO', $manager->resolveDisplayName('galaxy', 'sombrero')); } public function testRegisterResolverDuplicate(): void { $this->expectException(\OutOfBoundsException::class); $manager = $this->getManager(); $planetClosure = function ($name) { return ucfirst($name); }; $manager->registerDisplayNameResolver('planet', $planetClosure); $manager->registerDisplayNameResolver('planet', $planetClosure); } public function testRegisterResolverInvalidType(): void { $this->expectException(\InvalidArgumentException::class); $manager = $this->getManager(); $planetClosure = function ($name) { return ucfirst($name); }; $manager->registerDisplayNameResolver(1337, $planetClosure); } public function testResolveDisplayNameUnregisteredType(): void { $this->expectException(\OutOfBoundsException::class); $manager = $this->getManager(); $planetClosure = function ($name) { return ucfirst($name); }; $manager->registerDisplayNameResolver('planet', $planetClosure); $manager->resolveDisplayName('galaxy', 'sombrero'); } public function testResolveDisplayNameDirtyResolver(): void { $manager = $this->getManager(); $planetClosure = function () { return null; }; $manager->registerDisplayNameResolver('planet', $planetClosure); $this->assertTrue(is_string($manager->resolveDisplayName('planet', 'neptune'))); } private function skipIfNotSupport4ByteUTF() { if (!$this->getManager()->supportReactions()) { $this->markTestSkipped('MySQL doesn\'t support 4 byte UTF-8'); } } /** * @dataProvider providerTestReactionAddAndDelete * * @param IComment[] $comments * @param array $reactionsExpected * @return void */ public function testReactionAddAndDelete(array $comments, array $reactionsExpected): void { $this->skipIfNotSupport4ByteUTF(); $manager = $this->getManager(); $processedComments = $this->proccessComments($comments); $comment = end($processedComments); if ($comment->getParentId()) { $parent = $manager->get($comment->getParentId()); $this->assertEqualsCanonicalizing($reactionsExpected, $parent->getReactions()); } } public function providerTestReactionAddAndDelete(): array { return[ [ [ ['message', 'alice', 'comment', null], ], [], ], [ [ ['message', 'alice', 'comment', null], ['๐Ÿ‘', 'alice', 'reaction', 'message#alice'], ], ['๐Ÿ‘' => 1], ], [ [ ['message', 'alice', 'comment', null], ['๐Ÿ‘', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘', 'alice', 'reaction', 'message#alice'], ], ['๐Ÿ‘' => 1], ], [ [ ['message', 'alice', 'comment', null], ['๐Ÿ‘', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘', 'frank', 'reaction', 'message#alice'], ], ['๐Ÿ‘' => 2], ], [ [ ['message', 'alice', 'comment', null], ['๐Ÿ‘', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘', 'frank', 'reaction', 'message#alice'], ['๐Ÿ‘', 'frank', 'reaction_deleted', 'message#alice'], ], ['๐Ÿ‘' => 1], ], [ [ ['message', 'alice', 'comment', null], ['๐Ÿ‘', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘', 'frank', 'reaction', 'message#alice'], ['๐Ÿ‘', 'alice', 'reaction_deleted', 'message#alice'], ['๐Ÿ‘', 'frank', 'reaction_deleted', 'message#alice'], ], [], ], ]; } public function testResolveDisplayNameInvalidType(): void { $this->expectException(\InvalidArgumentException::class); $manager = $this->getManager(); $planetClosure = function () { return null; }; $manager->registerDisplayNameResolver('planet', $planetClosure); $this->assertTrue(is_string($manager->resolveDisplayName(1337, 'neptune'))); } /** * @param array $data * @return IComment[] */ private function proccessComments(array $data): array { /** @var IComment[] */ $comments = []; foreach ($data as $comment) { [$message, $actorId, $verb, $parentText] = $comment; $parentId = null; if ($parentText) { $parentId = (string)$comments[$parentText]->getId(); } $id = ''; if ($verb === 'reaction_deleted') { $id = $comments[$message . '#' . $actorId]->getId(); } $comment = $this->testSave($message, $actorId, $verb, $parentId, $id); $comments[$comment->getMessage() . '#' . $comment->getActorId()] = $comment; } return $comments; } /** * @dataProvider providerTestRetrieveAllReactions */ public function testRetrieveAllReactions(array $comments, array $expected): void { $this->skipIfNotSupport4ByteUTF(); $manager = $this->getManager(); $processedComments = $this->proccessComments($comments); $comment = reset($processedComments); $all = $manager->retrieveAllReactions($comment->getId()); $actual = array_map(function ($row) { return [ 'message' => $row->getMessage(), 'actorId' => $row->getActorId(), ]; }, $all); $this->assertEqualsCanonicalizing($expected, $actual); } public function providerTestRetrieveAllReactions(): array { return [ [ [ ['message', 'alice', 'comment', null], ], [], ], [ [ ['message', 'alice', 'comment', null], ['๐Ÿ‘', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘', 'frank', 'reaction', 'message#alice'], ], [ ['๐Ÿ‘', 'alice'], ['๐Ÿ‘', 'frank'], ], ], [ [ ['message', 'alice', 'comment', null], ['๐Ÿ‘', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘', 'frank', 'reaction', 'message#alice'], ], [ ['๐Ÿ‘', 'alice'], ['๐Ÿ‘', 'frank'], ], ], [# 600 reactions to cover chunk size when retrieve comments of reactions. [ ['message', 'alice', 'comment', null], ['๐Ÿ˜€', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ƒ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜„', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜†', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜…', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜‚', 'alice', 'reaction', 'message#alice'], ['๐Ÿคฃ', 'alice', 'reaction', 'message#alice'], ['๐Ÿฅฒ', 'alice', 'reaction', 'message#alice'], ['๐Ÿฅน', 'alice', 'reaction', 'message#alice'], ['โ˜บ๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜Š', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜‡', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™‚', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™ƒ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜‰', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜Œ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜', 'alice', 'reaction', 'message#alice'], ['๐Ÿฅฐ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜˜', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜—', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜™', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜š', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜‹', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜›', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜œ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคช', 'alice', 'reaction', 'message#alice'], ['๐Ÿคจ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง', 'alice', 'reaction', 'message#alice'], ['๐Ÿค“', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜Ž', 'alice', 'reaction', 'message#alice'], ['๐Ÿฅธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคฉ', 'alice', 'reaction', 'message#alice'], ['๐Ÿฅณ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜’', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ž', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜”', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜Ÿ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜•', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™', 'alice', 'reaction', 'message#alice'], ['โ˜น๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ฃ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜–', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ซ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ฉ', 'alice', 'reaction', 'message#alice'], ['๐Ÿฅบ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ข', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ญ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ฎโ€๐Ÿ’จ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ค', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ก', 'alice', 'reaction', 'message#alice'], ['๐Ÿคฌ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคฏ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ณ', 'alice', 'reaction', 'message#alice'], ['๐Ÿฅต', 'alice', 'reaction', 'message#alice'], ['๐Ÿฅถ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ฑ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜จ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ฐ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ฅ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜“', 'alice', 'reaction', 'message#alice'], ['๐Ÿซฃ', 'alice', 'reaction', 'message#alice'], ['๐Ÿค—', 'alice', 'reaction', 'message#alice'], ['๐Ÿซก', 'alice', 'reaction', 'message#alice'], ['๐Ÿค”', 'alice', 'reaction', 'message#alice'], ['๐Ÿซข', 'alice', 'reaction', 'message#alice'], ['๐Ÿคญ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคซ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคฅ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ถ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ถโ€๐ŸŒซ๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜‘', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ฌ', 'alice', 'reaction', 'message#alice'], ['๐Ÿซ ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™„', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ฏ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ฆ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ง', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ฎ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ฒ', 'alice', 'reaction', 'message#alice'], ['๐Ÿฅฑ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ด', 'alice', 'reaction', 'message#alice'], ['๐Ÿคค', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ช', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ต', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ตโ€๐Ÿ’ซ', 'alice', 'reaction', 'message#alice'], ['๐Ÿซฅ', 'alice', 'reaction', 'message#alice'], ['๐Ÿค', 'alice', 'reaction', 'message#alice'], ['๐Ÿฅด', 'alice', 'reaction', 'message#alice'], ['๐Ÿคข', 'alice', 'reaction', 'message#alice'], ['๐Ÿคฎ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคง', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ท', 'alice', 'reaction', 'message#alice'], ['๐Ÿค’', 'alice', 'reaction', 'message#alice'], ['๐Ÿค•', 'alice', 'reaction', 'message#alice'], ['๐Ÿค‘', 'alice', 'reaction', 'message#alice'], ['๐Ÿค ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ˆ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฟ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘น', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘บ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคก', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’ฉ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ป', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’€', 'alice', 'reaction', 'message#alice'], ['โ˜ ๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘พ', 'alice', 'reaction', 'message#alice'], ['๐Ÿค–', 'alice', 'reaction', 'message#alice'], ['๐ŸŽƒ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜บ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜น', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ป', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ผ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™€', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜ฟ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ˜พ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ถ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ง', 'alice', 'reaction', 'message#alice'], ['๐Ÿง’', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฆ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€๐Ÿฆฑ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘โ€๐Ÿฆฑ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐Ÿฆฑ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€๐Ÿฆฐ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘โ€๐Ÿฆฐ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐Ÿฆฐ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฑโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฑ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฑโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€๐Ÿฆณ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘โ€๐Ÿฆณ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐Ÿฆณ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€๐Ÿฆฒ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘โ€๐Ÿฆฒ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐Ÿฆฒ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง”โ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง”', 'alice', 'reaction', 'message#alice'], ['๐Ÿง”โ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ต', 'alice', 'reaction', 'message#alice'], ['๐Ÿง“', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ด', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฒ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ณโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ณ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ณโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง•', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฎโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฎ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฎโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ทโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ท', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ทโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’‚โ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’‚', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’‚โ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ•ต๏ธโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ•ต๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ•ต๏ธโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€โš•๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘โ€โš•๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€โš•๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€๐ŸŒพ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘โ€๐ŸŒพ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐ŸŒพ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€๐Ÿณ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘โ€๐Ÿณ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐Ÿณ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€๐ŸŽ“', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘โ€๐ŸŽ“', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐ŸŽ“', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€๐ŸŽค', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘โ€๐ŸŽค', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐ŸŽค', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€๐Ÿซ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘โ€๐Ÿซ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐Ÿซ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€๐Ÿญ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘โ€๐Ÿญ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐Ÿญ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€๐Ÿ’ป', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘โ€๐Ÿ’ป', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐Ÿ’ป', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€๐Ÿ’ผ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘โ€๐Ÿ’ผ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐Ÿ’ผ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€๐Ÿ”ง', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘โ€๐Ÿ”ง', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐Ÿ”ง', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€๐Ÿ”ฌ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘โ€๐Ÿ”ฌ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐Ÿ”ฌ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€๐ŸŽจ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘โ€๐ŸŽจ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐ŸŽจ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€๐Ÿš’', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘โ€๐Ÿš’', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐Ÿš’', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€โœˆ๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘โ€โœˆ๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€โœˆ๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€๐Ÿš€', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘โ€๐Ÿš€', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐Ÿš€', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€โš–๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘โ€โš–๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€โš–๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฐโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฐ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฐโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคตโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคต', 'alice', 'reaction', 'message#alice'], ['๐Ÿคตโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿซ…', 'alice', 'reaction', 'message#alice'], ['๐Ÿคด', 'alice', 'reaction', 'message#alice'], ['๐Ÿฅท', 'alice', 'reaction', 'message#alice'], ['๐Ÿฆธโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿฆธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿฆธโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿฆนโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿฆน', 'alice', 'reaction', 'message#alice'], ['๐Ÿฆนโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคถ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘โ€๐ŸŽ„', 'alice', 'reaction', 'message#alice'], ['๐ŸŽ…', 'alice', 'reaction', 'message#alice'], ['๐Ÿง™โ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง™', 'alice', 'reaction', 'message#alice'], ['๐Ÿง™โ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿงโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง', 'alice', 'reaction', 'message#alice'], ['๐Ÿงโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง›โ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง›', 'alice', 'reaction', 'message#alice'], ['๐Ÿง›โ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐ŸงŸโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐ŸงŸ', 'alice', 'reaction', 'message#alice'], ['๐ŸงŸโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿงžโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿงž', 'alice', 'reaction', 'message#alice'], ['๐Ÿงžโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿงœโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿงœ', 'alice', 'reaction', 'message#alice'], ['๐Ÿงœโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿงšโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿงš', 'alice', 'reaction', 'message#alice'], ['๐Ÿงšโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐ŸงŒ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ผ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคฐ', 'alice', 'reaction', 'message#alice'], ['๐Ÿซ„', 'alice', 'reaction', 'message#alice'], ['๐Ÿซƒ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคฑ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€๐Ÿผ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘โ€๐Ÿผ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐Ÿผ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™‡โ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™‡', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™‡โ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’โ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’โ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™…โ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™…', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™…โ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™†โ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™†', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™†โ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™‹โ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™‹', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™‹โ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿงโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง', 'alice', 'reaction', 'message#alice'], ['๐Ÿงโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคฆโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคฆ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคฆโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคทโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคท', 'alice', 'reaction', 'message#alice'], ['๐Ÿคทโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™Žโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™Ž', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™Žโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™โ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™โ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’‡โ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’‡', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’‡โ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’†โ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’†', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’†โ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง–โ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง–', 'alice', 'reaction', 'message#alice'], ['๐Ÿง–โ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’…', 'alice', 'reaction', 'message#alice'], ['๐Ÿคณ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’ƒ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ•บ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฏโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฏ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฏโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ•ด', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€๐Ÿฆฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘โ€๐Ÿฆฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐Ÿฆฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€๐Ÿฆผ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘โ€๐Ÿฆผ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐Ÿฆผ', 'alice', 'reaction', 'message#alice'], ['๐Ÿšถโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿšถ', 'alice', 'reaction', 'message#alice'], ['๐Ÿšถโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€๐Ÿฆฏ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘โ€๐Ÿฆฏ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐Ÿฆฏ', 'alice', 'reaction', 'message#alice'], ['๐ŸงŽโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐ŸงŽ', 'alice', 'reaction', 'message#alice'], ['๐ŸงŽโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿƒโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿƒ', 'alice', 'reaction', 'message#alice'], ['๐Ÿƒโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿงโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง', 'alice', 'reaction', 'message#alice'], ['๐Ÿงโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ญ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘โ€๐Ÿคโ€๐Ÿง‘', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฌ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ซ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ‘ฉ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’‘', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€โค๏ธโ€๐Ÿ‘จ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ‘จ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ’‹โ€๐Ÿ‘ฉ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€โค๏ธโ€๐Ÿ’‹โ€๐Ÿ‘จ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ’‹โ€๐Ÿ‘จ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ช', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ง', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ฆ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ง', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ฆ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ง', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ง', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐Ÿ‘ฆ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐Ÿ‘ง', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ฆ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ง', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€๐Ÿ‘ฆ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€๐Ÿ‘ง', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง', 'alice', 'reaction', 'message#alice'], ['๐Ÿ—ฃ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ค', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฅ', 'alice', 'reaction', 'message#alice'], ['๐Ÿซ‚', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘‹๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคš๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ–๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['โœ‹๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ––๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘Œ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐ŸคŒ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿค๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['โœŒ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคž๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿซฐ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐ŸคŸ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿค˜๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿค™๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿซต๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿซฑ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿซฒ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿซณ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿซด๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ˆ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘‰๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘†๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ–•๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘‡๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['โ˜๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘Ž๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['โœŠ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘Š๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿค›๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคœ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿซถ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™Œ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคฒ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['โœ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’…๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคณ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’ช๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿฆต๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿฆถ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘‚๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿฆป๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ƒ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ถ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ง๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง’๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฆ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿฆฑ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘๐Ÿฝโ€๐Ÿฆฑ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐Ÿฆฑ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿฆฐ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘๐Ÿฝโ€๐Ÿฆฐ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐Ÿฆฐ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฑ๐Ÿฝโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฑ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฑ๐Ÿฝโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿฆณ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘๐Ÿฝโ€๐Ÿฆณ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐Ÿฆณ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿฆฒ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘๐Ÿฝโ€๐Ÿฆฒ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐Ÿฆฒ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง”๐Ÿฝโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง”๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง”๐Ÿฝโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ต๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง“๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ด๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฒ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ณ๐Ÿฝโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ณ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ณ๐Ÿฝโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง•๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฎ๐Ÿฝโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฎ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฎ๐Ÿฝโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ท๐Ÿฝโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ท๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ท๐Ÿฝโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’‚๐Ÿฝโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’‚๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’‚๐Ÿฝโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ•ต๐Ÿฝโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ•ต๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ•ต๐Ÿฝโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€โš•๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘๐Ÿฝโ€โš•๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จ๐Ÿฝโ€โš•๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐ŸŒพ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘๐Ÿฝโ€๐ŸŒพ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐ŸŒพ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿณ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘๐Ÿฝโ€๐Ÿณ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐Ÿณ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐ŸŽ“', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘๐Ÿฝโ€๐ŸŽ“', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐ŸŽ“', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐ŸŽค', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘๐Ÿฝโ€๐ŸŽค', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐ŸŽค', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿซ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘๐Ÿฝโ€๐Ÿซ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐Ÿซ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿญ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘๐Ÿฝโ€๐Ÿญ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐Ÿญ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿ’ป', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘๐Ÿฝโ€๐Ÿ’ป', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐Ÿ’ป', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿ’ผ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘๐Ÿฝโ€๐Ÿ’ผ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐Ÿ’ผ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿ”ง', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘๐Ÿฝโ€๐Ÿ”ง', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐Ÿ”ง', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿ”ฌ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘๐Ÿฝโ€๐Ÿ”ฌ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐Ÿ”ฌ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐ŸŽจ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘๐Ÿฝโ€๐ŸŽจ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐ŸŽจ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿš’', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘๐Ÿฝโ€๐Ÿš’', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐Ÿš’', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€โœˆ๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘๐Ÿฝโ€โœˆ๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จ๐Ÿฝโ€โœˆ๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿš€', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘๐Ÿฝโ€๐Ÿš€', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐Ÿš€', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€โš–๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘๐Ÿฝโ€โš–๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จ๐Ÿฝโ€โš–๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฐ๐Ÿฝโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฐ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฐ๐Ÿฝโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคต๐Ÿฝโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคต๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคต๐Ÿฝโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ธ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿซ…๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคด๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿฅท๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿฆธ๐Ÿฝโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿฆธ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿฆธ๐Ÿฝโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿฆน๐Ÿฝโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿฆน๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿฆน๐Ÿฝโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคถ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘๐Ÿฝโ€๐ŸŽ„', 'alice', 'reaction', 'message#alice'], ['๐ŸŽ…๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง™๐Ÿฝโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง™๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง™๐Ÿฝโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง๐Ÿฝโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง๐Ÿฝโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง›๐Ÿฝโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง›๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง›๐Ÿฝโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿงœ๐Ÿฝโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿงœ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿงœ๐Ÿฝโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿงš๐Ÿฝโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿงš๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿงš๐Ÿฝโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ผ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคฐ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿซ„๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿซƒ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคฑ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿผ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘๐Ÿฝโ€๐Ÿผ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐Ÿผ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™‡๐Ÿฝโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™‡๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™‡๐Ÿฝโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’๐Ÿฝโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’๐Ÿฝโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™…๐Ÿฝโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™…๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™…๐Ÿฝโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™†๐Ÿฝโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™†๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™†๐Ÿฝโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™‹๐Ÿฝโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™‹๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™‹๐Ÿฝโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง๐Ÿฝโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง๐Ÿฝโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคฆ๐Ÿฝโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคฆ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคฆ๐Ÿฝโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคท๐Ÿฝโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคท๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿคท๐Ÿฝโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™Ž๐Ÿฝโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™Ž๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™Ž๐Ÿฝโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™๐Ÿฝโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ™๐Ÿฝโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’‡๐Ÿฝโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’‡๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’‡๐Ÿฝโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’†๐Ÿฝโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’†๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’†๐Ÿฝโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง–๐Ÿฝโ€โ™€๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง–๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง–๐Ÿฝโ€โ™‚๏ธ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ’ƒ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ•บ๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ•ด๐Ÿฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿฆฝ', 'alice', 'reaction', 'message#alice'], ['๐Ÿง‘๐Ÿฝโ€๐Ÿฆฝ', 'alice', 'reaction', 'message#alice'], ], [ ['๐Ÿ˜€', 'alice'], ['๐Ÿ˜ƒ', 'alice'], ['๐Ÿ˜„', 'alice'], ['๐Ÿ˜', 'alice'], ['๐Ÿ˜†', 'alice'], ['๐Ÿ˜…', 'alice'], ['๐Ÿ˜‚', 'alice'], ['๐Ÿคฃ', 'alice'], ['๐Ÿฅฒ', 'alice'], ['๐Ÿฅน', 'alice'], ['โ˜บ๏ธ', 'alice'], ['๐Ÿ˜Š', 'alice'], ['๐Ÿ˜‡', 'alice'], ['๐Ÿ™‚', 'alice'], ['๐Ÿ™ƒ', 'alice'], ['๐Ÿ˜‰', 'alice'], ['๐Ÿ˜Œ', 'alice'], ['๐Ÿ˜', 'alice'], ['๐Ÿฅฐ', 'alice'], ['๐Ÿ˜˜', 'alice'], ['๐Ÿ˜—', 'alice'], ['๐Ÿ˜™', 'alice'], ['๐Ÿ˜š', 'alice'], ['๐Ÿ˜‹', 'alice'], ['๐Ÿ˜›', 'alice'], ['๐Ÿ˜', 'alice'], ['๐Ÿ˜œ', 'alice'], ['๐Ÿคช', 'alice'], ['๐Ÿคจ', 'alice'], ['๐Ÿง', 'alice'], ['๐Ÿค“', 'alice'], ['๐Ÿ˜Ž', 'alice'], ['๐Ÿฅธ', 'alice'], ['๐Ÿคฉ', 'alice'], ['๐Ÿฅณ', 'alice'], ['๐Ÿ˜', 'alice'], ['๐Ÿ˜’', 'alice'], ['๐Ÿ˜ž', 'alice'], ['๐Ÿ˜”', 'alice'], ['๐Ÿ˜Ÿ', 'alice'], ['๐Ÿ˜•', 'alice'], ['๐Ÿ™', 'alice'], ['โ˜น๏ธ', 'alice'], ['๐Ÿ˜ฃ', 'alice'], ['๐Ÿ˜–', 'alice'], ['๐Ÿ˜ซ', 'alice'], ['๐Ÿ˜ฉ', 'alice'], ['๐Ÿฅบ', 'alice'], ['๐Ÿ˜ข', 'alice'], ['๐Ÿ˜ญ', 'alice'], ['๐Ÿ˜ฎโ€๐Ÿ’จ', 'alice'], ['๐Ÿ˜ค', 'alice'], ['๐Ÿ˜ ', 'alice'], ['๐Ÿ˜ก', 'alice'], ['๐Ÿคฌ', 'alice'], ['๐Ÿคฏ', 'alice'], ['๐Ÿ˜ณ', 'alice'], ['๐Ÿฅต', 'alice'], ['๐Ÿฅถ', 'alice'], ['๐Ÿ˜ฑ', 'alice'], ['๐Ÿ˜จ', 'alice'], ['๐Ÿ˜ฐ', 'alice'], ['๐Ÿ˜ฅ', 'alice'], ['๐Ÿ˜“', 'alice'], ['๐Ÿซฃ', 'alice'], ['๐Ÿค—', 'alice'], ['๐Ÿซก', 'alice'], ['๐Ÿค”', 'alice'], ['๐Ÿซข', 'alice'], ['๐Ÿคญ', 'alice'], ['๐Ÿคซ', 'alice'], ['๐Ÿคฅ', 'alice'], ['๐Ÿ˜ถ', 'alice'], ['๐Ÿ˜ถโ€๐ŸŒซ๏ธ', 'alice'], ['๐Ÿ˜', 'alice'], ['๐Ÿ˜‘', 'alice'], ['๐Ÿ˜ฌ', 'alice'], ['๐Ÿซ ', 'alice'], ['๐Ÿ™„', 'alice'], ['๐Ÿ˜ฏ', 'alice'], ['๐Ÿ˜ฆ', 'alice'], ['๐Ÿ˜ง', 'alice'], ['๐Ÿ˜ฎ', 'alice'], ['๐Ÿ˜ฒ', 'alice'], ['๐Ÿฅฑ', 'alice'], ['๐Ÿ˜ด', 'alice'], ['๐Ÿคค', 'alice'], ['๐Ÿ˜ช', 'alice'], ['๐Ÿ˜ต', 'alice'], ['๐Ÿ˜ตโ€๐Ÿ’ซ', 'alice'], ['๐Ÿซฅ', 'alice'], ['๐Ÿค', 'alice'], ['๐Ÿฅด', 'alice'], ['๐Ÿคข', 'alice'], ['๐Ÿคฎ', 'alice'], ['๐Ÿคง', 'alice'], ['๐Ÿ˜ท', 'alice'], ['๐Ÿค’', 'alice'], ['๐Ÿค•', 'alice'], ['๐Ÿค‘', 'alice'], ['๐Ÿค ', 'alice'], ['๐Ÿ˜ˆ', 'alice'], ['๐Ÿ‘ฟ', 'alice'], ['๐Ÿ‘น', 'alice'], ['๐Ÿ‘บ', 'alice'], ['๐Ÿคก', 'alice'], ['๐Ÿ’ฉ', 'alice'], ['๐Ÿ‘ป', 'alice'], ['๐Ÿ’€', 'alice'], ['โ˜ ๏ธ', 'alice'], ['๐Ÿ‘ฝ', 'alice'], ['๐Ÿ‘พ', 'alice'], ['๐Ÿค–', 'alice'], ['๐ŸŽƒ', 'alice'], ['๐Ÿ˜บ', 'alice'], ['๐Ÿ˜ธ', 'alice'], ['๐Ÿ˜น', 'alice'], ['๐Ÿ˜ป', 'alice'], ['๐Ÿ˜ผ', 'alice'], ['๐Ÿ˜ฝ', 'alice'], ['๐Ÿ™€', 'alice'], ['๐Ÿ˜ฟ', 'alice'], ['๐Ÿ˜พ', 'alice'], ['๐Ÿ‘ถ', 'alice'], ['๐Ÿ‘ง', 'alice'], ['๐Ÿง’', 'alice'], ['๐Ÿ‘ฆ', 'alice'], ['๐Ÿ‘ฉ', 'alice'], ['๐Ÿง‘', 'alice'], ['๐Ÿ‘จ', 'alice'], ['๐Ÿ‘ฉโ€๐Ÿฆฑ', 'alice'], ['๐Ÿง‘โ€๐Ÿฆฑ', 'alice'], ['๐Ÿ‘จโ€๐Ÿฆฑ', 'alice'], ['๐Ÿ‘ฉโ€๐Ÿฆฐ', 'alice'], ['๐Ÿง‘โ€๐Ÿฆฐ', 'alice'], ['๐Ÿ‘จโ€๐Ÿฆฐ', 'alice'], ['๐Ÿ‘ฑโ€โ™€๏ธ', 'alice'], ['๐Ÿ‘ฑ', 'alice'], ['๐Ÿ‘ฑโ€โ™‚๏ธ', 'alice'], ['๐Ÿ‘ฉโ€๐Ÿฆณ', 'alice'], ['๐Ÿง‘โ€๐Ÿฆณ', 'alice'], ['๐Ÿ‘จโ€๐Ÿฆณ', 'alice'], ['๐Ÿ‘ฉโ€๐Ÿฆฒ', 'alice'], ['๐Ÿง‘โ€๐Ÿฆฒ', 'alice'], ['๐Ÿ‘จโ€๐Ÿฆฒ', 'alice'], ['๐Ÿง”โ€โ™€๏ธ', 'alice'], ['๐Ÿง”', 'alice'], ['๐Ÿง”โ€โ™‚๏ธ', 'alice'], ['๐Ÿ‘ต', 'alice'], ['๐Ÿง“', 'alice'], ['๐Ÿ‘ด', 'alice'], ['๐Ÿ‘ฒ', 'alice'], ['๐Ÿ‘ณโ€โ™€๏ธ', 'alice'], ['๐Ÿ‘ณ', 'alice'], ['๐Ÿ‘ณโ€โ™‚๏ธ', 'alice'], ['๐Ÿง•', 'alice'], ['๐Ÿ‘ฎโ€โ™€๏ธ', 'alice'], ['๐Ÿ‘ฎ', 'alice'], ['๐Ÿ‘ฎโ€โ™‚๏ธ', 'alice'], ['๐Ÿ‘ทโ€โ™€๏ธ', 'alice'], ['๐Ÿ‘ท', 'alice'], ['๐Ÿ‘ทโ€โ™‚๏ธ', 'alice'], ['๐Ÿ’‚โ€โ™€๏ธ', 'alice'], ['๐Ÿ’‚', 'alice'], ['๐Ÿ’‚โ€โ™‚๏ธ', 'alice'], ['๐Ÿ•ต๏ธโ€โ™€๏ธ', 'alice'], ['๐Ÿ•ต๏ธ', 'alice'], ['๐Ÿ•ต๏ธโ€โ™‚๏ธ', 'alice'], ['๐Ÿ‘ฉโ€โš•๏ธ', 'alice'], ['๐Ÿง‘โ€โš•๏ธ', 'alice'], ['๐Ÿ‘จโ€โš•๏ธ', 'alice'], ['๐Ÿ‘ฉโ€๐ŸŒพ', 'alice'], ['๐Ÿง‘โ€๐ŸŒพ', 'alice'], ['๐Ÿ‘จโ€๐ŸŒพ', 'alice'], ['๐Ÿ‘ฉโ€๐Ÿณ', 'alice'], ['๐Ÿง‘โ€๐Ÿณ', 'alice'], ['๐Ÿ‘จโ€๐Ÿณ', 'alice'], ['๐Ÿ‘ฉโ€๐ŸŽ“', 'alice'], ['๐Ÿง‘โ€๐ŸŽ“', 'alice'], ['๐Ÿ‘จโ€๐ŸŽ“', 'alice'], ['๐Ÿ‘ฉโ€๐ŸŽค', 'alice'], ['๐Ÿง‘โ€๐ŸŽค', 'alice'], ['๐Ÿ‘จโ€๐ŸŽค', 'alice'], ['๐Ÿ‘ฉโ€๐Ÿซ', 'alice'], ['๐Ÿง‘โ€๐Ÿซ', 'alice'], ['๐Ÿ‘จโ€๐Ÿซ', 'alice'], ['๐Ÿ‘ฉโ€๐Ÿญ', 'alice'], ['๐Ÿง‘โ€๐Ÿญ', 'alice'], ['๐Ÿ‘จโ€๐Ÿญ', 'alice'], ['๐Ÿ‘ฉโ€๐Ÿ’ป', 'alice'], ['๐Ÿง‘โ€๐Ÿ’ป', 'alice'], ['๐Ÿ‘จโ€๐Ÿ’ป', 'alice'], ['๐Ÿ‘ฉโ€๐Ÿ’ผ', 'alice'], ['๐Ÿง‘โ€๐Ÿ’ผ', 'alice'], ['๐Ÿ‘จโ€๐Ÿ’ผ', 'alice'], ['๐Ÿ‘ฉโ€๐Ÿ”ง', 'alice'], ['๐Ÿง‘โ€๐Ÿ”ง', 'alice'], ['๐Ÿ‘จโ€๐Ÿ”ง', 'alice'], ['๐Ÿ‘ฉโ€๐Ÿ”ฌ', 'alice'], ['๐Ÿง‘โ€๐Ÿ”ฌ', 'alice'], ['๐Ÿ‘จโ€๐Ÿ”ฌ', 'alice'], ['๐Ÿ‘ฉโ€๐ŸŽจ', 'alice'], ['๐Ÿง‘โ€๐ŸŽจ', 'alice'], ['๐Ÿ‘จโ€๐ŸŽจ', 'alice'], ['๐Ÿ‘ฉโ€๐Ÿš’', 'alice'], ['๐Ÿง‘โ€๐Ÿš’', 'alice'], ['๐Ÿ‘จโ€๐Ÿš’', 'alice'], ['๐Ÿ‘ฉโ€โœˆ๏ธ', 'alice'], ['๐Ÿง‘โ€โœˆ๏ธ', 'alice'], ['๐Ÿ‘จโ€โœˆ๏ธ', 'alice'], ['๐Ÿ‘ฉโ€๐Ÿš€', 'alice'], ['๐Ÿง‘โ€๐Ÿš€', 'alice'], ['๐Ÿ‘จโ€๐Ÿš€', 'alice'], ['๐Ÿ‘ฉโ€โš–๏ธ', 'alice'], ['๐Ÿง‘โ€โš–๏ธ', 'alice'], ['๐Ÿ‘จโ€โš–๏ธ', 'alice'], ['๐Ÿ‘ฐโ€โ™€๏ธ', 'alice'], ['๐Ÿ‘ฐ', 'alice'], ['๐Ÿ‘ฐโ€โ™‚๏ธ', 'alice'], ['๐Ÿคตโ€โ™€๏ธ', 'alice'], ['๐Ÿคต', 'alice'], ['๐Ÿคตโ€โ™‚๏ธ', 'alice'], ['๐Ÿ‘ธ', 'alice'], ['๐Ÿซ…', 'alice'], ['๐Ÿคด', 'alice'], ['๐Ÿฅท', 'alice'], ['๐Ÿฆธโ€โ™€๏ธ', 'alice'], ['๐Ÿฆธ', 'alice'], ['๐Ÿฆธโ€โ™‚๏ธ', 'alice'], ['๐Ÿฆนโ€โ™€๏ธ', 'alice'], ['๐Ÿฆน', 'alice'], ['๐Ÿฆนโ€โ™‚๏ธ', 'alice'], ['๐Ÿคถ', 'alice'], ['๐Ÿง‘โ€๐ŸŽ„', 'alice'], ['๐ŸŽ…', 'alice'], ['๐Ÿง™โ€โ™€๏ธ', 'alice'], ['๐Ÿง™', 'alice'], ['๐Ÿง™โ€โ™‚๏ธ', 'alice'], ['๐Ÿงโ€โ™€๏ธ', 'alice'], ['๐Ÿง', 'alice'], ['๐Ÿงโ€โ™‚๏ธ', 'alice'], ['๐Ÿง›โ€โ™€๏ธ', 'alice'], ['๐Ÿง›', 'alice'], ['๐Ÿง›โ€โ™‚๏ธ', 'alice'], ['๐ŸงŸโ€โ™€๏ธ', 'alice'], ['๐ŸงŸ', 'alice'], ['๐ŸงŸโ€โ™‚๏ธ', 'alice'], ['๐Ÿงžโ€โ™€๏ธ', 'alice'], ['๐Ÿงž', 'alice'], ['๐Ÿงžโ€โ™‚๏ธ', 'alice'], ['๐Ÿงœโ€โ™€๏ธ', 'alice'], ['๐Ÿงœ', 'alice'], ['๐Ÿงœโ€โ™‚๏ธ', 'alice'], ['๐Ÿงšโ€โ™€๏ธ', 'alice'], ['๐Ÿงš', 'alice'], ['๐Ÿงšโ€โ™‚๏ธ', 'alice'], ['๐ŸงŒ', 'alice'], ['๐Ÿ‘ผ', 'alice'], ['๐Ÿคฐ', 'alice'], ['๐Ÿซ„', 'alice'], ['๐Ÿซƒ', 'alice'], ['๐Ÿคฑ', 'alice'], ['๐Ÿ‘ฉโ€๐Ÿผ', 'alice'], ['๐Ÿง‘โ€๐Ÿผ', 'alice'], ['๐Ÿ‘จโ€๐Ÿผ', 'alice'], ['๐Ÿ™‡โ€โ™€๏ธ', 'alice'], ['๐Ÿ™‡', 'alice'], ['๐Ÿ™‡โ€โ™‚๏ธ', 'alice'], ['๐Ÿ’โ€โ™€๏ธ', 'alice'], ['๐Ÿ’', 'alice'], ['๐Ÿ’โ€โ™‚๏ธ', 'alice'], ['๐Ÿ™…โ€โ™€๏ธ', 'alice'], ['๐Ÿ™…', 'alice'], ['๐Ÿ™…โ€โ™‚๏ธ', 'alice'], ['๐Ÿ™†โ€โ™€๏ธ', 'alice'], ['๐Ÿ™†', 'alice'], ['๐Ÿ™†โ€โ™‚๏ธ', 'alice'], ['๐Ÿ™‹โ€โ™€๏ธ', 'alice'], ['๐Ÿ™‹', 'alice'], ['๐Ÿ™‹โ€โ™‚๏ธ', 'alice'], ['๐Ÿงโ€โ™€๏ธ', 'alice'], ['๐Ÿง', 'alice'], ['๐Ÿงโ€โ™‚๏ธ', 'alice'], ['๐Ÿคฆโ€โ™€๏ธ', 'alice'], ['๐Ÿคฆ', 'alice'], ['๐Ÿคฆโ€โ™‚๏ธ', 'alice'], ['๐Ÿคทโ€โ™€๏ธ', 'alice'], ['๐Ÿคท', 'alice'], ['๐Ÿคทโ€โ™‚๏ธ', 'alice'], ['๐Ÿ™Žโ€โ™€๏ธ', 'alice'], ['๐Ÿ™Ž', 'alice'], ['๐Ÿ™Žโ€โ™‚๏ธ', 'alice'], ['๐Ÿ™โ€โ™€๏ธ', 'alice'], ['๐Ÿ™', 'alice'], ['๐Ÿ™โ€โ™‚๏ธ', 'alice'], ['๐Ÿ’‡โ€โ™€๏ธ', 'alice'], ['๐Ÿ’‡', 'alice'], ['๐Ÿ’‡โ€โ™‚๏ธ', 'alice'], ['๐Ÿ’†โ€โ™€๏ธ', 'alice'], ['๐Ÿ’†', 'alice'], ['๐Ÿ’†โ€โ™‚๏ธ', 'alice'], ['๐Ÿง–โ€โ™€๏ธ', 'alice'], ['๐Ÿง–', 'alice'], ['๐Ÿง–โ€โ™‚๏ธ', 'alice'], ['๐Ÿ’…', 'alice'], ['๐Ÿคณ', 'alice'], ['๐Ÿ’ƒ', 'alice'], ['๐Ÿ•บ', 'alice'], ['๐Ÿ‘ฏโ€โ™€๏ธ', 'alice'], ['๐Ÿ‘ฏ', 'alice'], ['๐Ÿ‘ฏโ€โ™‚๏ธ', 'alice'], ['๐Ÿ•ด', 'alice'], ['๐Ÿ‘ฉโ€๐Ÿฆฝ', 'alice'], ['๐Ÿง‘โ€๐Ÿฆฝ', 'alice'], ['๐Ÿ‘จโ€๐Ÿฆฝ', 'alice'], ['๐Ÿ‘ฉโ€๐Ÿฆผ', 'alice'], ['๐Ÿง‘โ€๐Ÿฆผ', 'alice'], ['๐Ÿ‘จโ€๐Ÿฆผ', 'alice'], ['๐Ÿšถโ€โ™€๏ธ', 'alice'], ['๐Ÿšถ', 'alice'], ['๐Ÿšถโ€โ™‚๏ธ', 'alice'], ['๐Ÿ‘ฉโ€๐Ÿฆฏ', 'alice'], ['๐Ÿง‘โ€๐Ÿฆฏ', 'alice'], ['๐Ÿ‘จโ€๐Ÿฆฏ', 'alice'], ['๐ŸงŽโ€โ™€๏ธ', 'alice'], ['๐ŸงŽ', 'alice'], ['๐ŸงŽโ€โ™‚๏ธ', 'alice'], ['๐Ÿƒโ€โ™€๏ธ', 'alice'], ['๐Ÿƒ', 'alice'], ['๐Ÿƒโ€โ™‚๏ธ', 'alice'], ['๐Ÿงโ€โ™€๏ธ', 'alice'], ['๐Ÿง', 'alice'], ['๐Ÿงโ€โ™‚๏ธ', 'alice'], ['๐Ÿ‘ญ', 'alice'], ['๐Ÿง‘โ€๐Ÿคโ€๐Ÿง‘', 'alice'], ['๐Ÿ‘ฌ', 'alice'], ['๐Ÿ‘ซ', 'alice'], ['๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ‘ฉ', 'alice'], ['๐Ÿ’‘', 'alice'], ['๐Ÿ‘จโ€โค๏ธโ€๐Ÿ‘จ', 'alice'], ['๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ‘จ', 'alice'], ['๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ’‹โ€๐Ÿ‘ฉ', 'alice'], ['๐Ÿ’', 'alice'], ['๐Ÿ‘จโ€โค๏ธโ€๐Ÿ’‹โ€๐Ÿ‘จ', 'alice'], ['๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ’‹โ€๐Ÿ‘จ', 'alice'], ['๐Ÿ‘ช', 'alice'], ['๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆ', 'alice'], ['๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ง', 'alice'], ['๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ', 'alice'], ['๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ', 'alice'], ['๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง', 'alice'], ['๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ฆ', 'alice'], ['๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ง', 'alice'], ['๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ฆ', 'alice'], ['๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ', 'alice'], ['๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ง', 'alice'], ['๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆ', 'alice'], ['๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ง', 'alice'], ['๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ', 'alice'], ['๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ', 'alice'], ['๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง', 'alice'], ['๐Ÿ‘จโ€๐Ÿ‘ฆ', 'alice'], ['๐Ÿ‘จโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ', 'alice'], ['๐Ÿ‘จโ€๐Ÿ‘ง', 'alice'], ['๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ฆ', 'alice'], ['๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ง', 'alice'], ['๐Ÿ‘ฉโ€๐Ÿ‘ฆ', 'alice'], ['๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ', 'alice'], ['๐Ÿ‘ฉโ€๐Ÿ‘ง', 'alice'], ['๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ', 'alice'], ['๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง', 'alice'], ['๐Ÿ—ฃ', 'alice'], ['๐Ÿ‘ค', 'alice'], ['๐Ÿ‘ฅ', 'alice'], ['๐Ÿซ‚', 'alice'], ['๐Ÿ‘‹๐Ÿฝ', 'alice'], ['๐Ÿคš๐Ÿฝ', 'alice'], ['๐Ÿ–๐Ÿฝ', 'alice'], ['โœ‹๐Ÿฝ', 'alice'], ['๐Ÿ––๐Ÿฝ', 'alice'], ['๐Ÿ‘Œ๐Ÿฝ', 'alice'], ['๐ŸคŒ๐Ÿฝ', 'alice'], ['๐Ÿค๐Ÿฝ', 'alice'], ['โœŒ๐Ÿฝ', 'alice'], ['๐Ÿคž๐Ÿฝ', 'alice'], ['๐Ÿซฐ๐Ÿฝ', 'alice'], ['๐ŸคŸ๐Ÿฝ', 'alice'], ['๐Ÿค˜๐Ÿฝ', 'alice'], ['๐Ÿค™๐Ÿฝ', 'alice'], ['๐Ÿซต๐Ÿฝ', 'alice'], ['๐Ÿซฑ๐Ÿฝ', 'alice'], ['๐Ÿซฒ๐Ÿฝ', 'alice'], ['๐Ÿซณ๐Ÿฝ', 'alice'], ['๐Ÿซด๐Ÿฝ', 'alice'], ['๐Ÿ‘ˆ๐Ÿฝ', 'alice'], ['๐Ÿ‘‰๐Ÿฝ', 'alice'], ['๐Ÿ‘†๐Ÿฝ', 'alice'], ['๐Ÿ–•๐Ÿฝ', 'alice'], ['๐Ÿ‘‡๐Ÿฝ', 'alice'], ['โ˜๐Ÿฝ', 'alice'], ['๐Ÿ‘๐Ÿฝ', 'alice'], ['๐Ÿ‘Ž๐Ÿฝ', 'alice'], ['โœŠ๐Ÿฝ', 'alice'], ['๐Ÿ‘Š๐Ÿฝ', 'alice'], ['๐Ÿค›๐Ÿฝ', 'alice'], ['๐Ÿคœ๐Ÿฝ', 'alice'], ['๐Ÿ‘๐Ÿฝ', 'alice'], ['๐Ÿซถ๐Ÿฝ', 'alice'], ['๐Ÿ™Œ๐Ÿฝ', 'alice'], ['๐Ÿ‘๐Ÿฝ', 'alice'], ['๐Ÿคฒ๐Ÿฝ', 'alice'], ['๐Ÿ™๐Ÿฝ', 'alice'], ['โœ๐Ÿฝ', 'alice'], ['๐Ÿ’…๐Ÿฝ', 'alice'], ['๐Ÿคณ๐Ÿฝ', 'alice'], ['๐Ÿ’ช๐Ÿฝ', 'alice'], ['๐Ÿฆต๐Ÿฝ', 'alice'], ['๐Ÿฆถ๐Ÿฝ', 'alice'], ['๐Ÿ‘‚๐Ÿฝ', 'alice'], ['๐Ÿฆป๐Ÿฝ', 'alice'], ['๐Ÿ‘ƒ๐Ÿฝ', 'alice'], ['๐Ÿ‘ถ๐Ÿฝ', 'alice'], ['๐Ÿ‘ง๐Ÿฝ', 'alice'], ['๐Ÿง’๐Ÿฝ', 'alice'], ['๐Ÿ‘ฆ๐Ÿฝ', 'alice'], ['๐Ÿ‘ฉ๐Ÿฝ', 'alice'], ['๐Ÿง‘๐Ÿฝ', 'alice'], ['๐Ÿ‘จ๐Ÿฝ', 'alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿฆฑ', 'alice'], ['๐Ÿง‘๐Ÿฝโ€๐Ÿฆฑ', 'alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐Ÿฆฑ', 'alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿฆฐ', 'alice'], ['๐Ÿง‘๐Ÿฝโ€๐Ÿฆฐ', 'alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐Ÿฆฐ', 'alice'], ['๐Ÿ‘ฑ๐Ÿฝโ€โ™€๏ธ', 'alice'], ['๐Ÿ‘ฑ๐Ÿฝ', 'alice'], ['๐Ÿ‘ฑ๐Ÿฝโ€โ™‚๏ธ', 'alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿฆณ', 'alice'], ['๐Ÿง‘๐Ÿฝโ€๐Ÿฆณ', 'alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐Ÿฆณ', 'alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿฆฒ', 'alice'], ['๐Ÿง‘๐Ÿฝโ€๐Ÿฆฒ', 'alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐Ÿฆฒ', 'alice'], ['๐Ÿง”๐Ÿฝโ€โ™€๏ธ', 'alice'], ['๐Ÿง”๐Ÿฝ', 'alice'], ['๐Ÿง”๐Ÿฝโ€โ™‚๏ธ', 'alice'], ['๐Ÿ‘ต๐Ÿฝ', 'alice'], ['๐Ÿง“๐Ÿฝ', 'alice'], ['๐Ÿ‘ด๐Ÿฝ', 'alice'], ['๐Ÿ‘ฒ๐Ÿฝ', 'alice'], ['๐Ÿ‘ณ๐Ÿฝโ€โ™€๏ธ', 'alice'], ['๐Ÿ‘ณ๐Ÿฝ', 'alice'], ['๐Ÿ‘ณ๐Ÿฝโ€โ™‚๏ธ', 'alice'], ['๐Ÿง•๐Ÿฝ', 'alice'], ['๐Ÿ‘ฎ๐Ÿฝโ€โ™€๏ธ', 'alice'], ['๐Ÿ‘ฎ๐Ÿฝ', 'alice'], ['๐Ÿ‘ฎ๐Ÿฝโ€โ™‚๏ธ', 'alice'], ['๐Ÿ‘ท๐Ÿฝโ€โ™€๏ธ', 'alice'], ['๐Ÿ‘ท๐Ÿฝ', 'alice'], ['๐Ÿ‘ท๐Ÿฝโ€โ™‚๏ธ', 'alice'], ['๐Ÿ’‚๐Ÿฝโ€โ™€๏ธ', 'alice'], ['๐Ÿ’‚๐Ÿฝ', 'alice'], ['๐Ÿ’‚๐Ÿฝโ€โ™‚๏ธ', 'alice'], ['๐Ÿ•ต๐Ÿฝโ€โ™€๏ธ', 'alice'], ['๐Ÿ•ต๐Ÿฝ', 'alice'], ['๐Ÿ•ต๐Ÿฝโ€โ™‚๏ธ', 'alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€โš•๏ธ', 'alice'], ['๐Ÿง‘๐Ÿฝโ€โš•๏ธ', 'alice'], ['๐Ÿ‘จ๐Ÿฝโ€โš•๏ธ', 'alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐ŸŒพ', 'alice'], ['๐Ÿง‘๐Ÿฝโ€๐ŸŒพ', 'alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐ŸŒพ', 'alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿณ', 'alice'], ['๐Ÿง‘๐Ÿฝโ€๐Ÿณ', 'alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐Ÿณ', 'alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐ŸŽ“', 'alice'], ['๐Ÿง‘๐Ÿฝโ€๐ŸŽ“', 'alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐ŸŽ“', 'alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐ŸŽค', 'alice'], ['๐Ÿง‘๐Ÿฝโ€๐ŸŽค', 'alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐ŸŽค', 'alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿซ', 'alice'], ['๐Ÿง‘๐Ÿฝโ€๐Ÿซ', 'alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐Ÿซ', 'alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿญ', 'alice'], ['๐Ÿง‘๐Ÿฝโ€๐Ÿญ', 'alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐Ÿญ', 'alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿ’ป', 'alice'], ['๐Ÿง‘๐Ÿฝโ€๐Ÿ’ป', 'alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐Ÿ’ป', 'alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿ’ผ', 'alice'], ['๐Ÿง‘๐Ÿฝโ€๐Ÿ’ผ', 'alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐Ÿ’ผ', 'alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿ”ง', 'alice'], ['๐Ÿง‘๐Ÿฝโ€๐Ÿ”ง', 'alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐Ÿ”ง', 'alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿ”ฌ', 'alice'], ['๐Ÿง‘๐Ÿฝโ€๐Ÿ”ฌ', 'alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐Ÿ”ฌ', 'alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐ŸŽจ', 'alice'], ['๐Ÿง‘๐Ÿฝโ€๐ŸŽจ', 'alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐ŸŽจ', 'alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿš’', 'alice'], ['๐Ÿง‘๐Ÿฝโ€๐Ÿš’', 'alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐Ÿš’', 'alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€โœˆ๏ธ', 'alice'], ['๐Ÿง‘๐Ÿฝโ€โœˆ๏ธ', 'alice'], ['๐Ÿ‘จ๐Ÿฝโ€โœˆ๏ธ', 'alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿš€', 'alice'], ['๐Ÿง‘๐Ÿฝโ€๐Ÿš€', 'alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐Ÿš€', 'alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€โš–๏ธ', 'alice'], ['๐Ÿง‘๐Ÿฝโ€โš–๏ธ', 'alice'], ['๐Ÿ‘จ๐Ÿฝโ€โš–๏ธ', 'alice'], ['๐Ÿ‘ฐ๐Ÿฝโ€โ™€๏ธ', 'alice'], ['๐Ÿ‘ฐ๐Ÿฝ', 'alice'], ['๐Ÿ‘ฐ๐Ÿฝโ€โ™‚๏ธ', 'alice'], ['๐Ÿคต๐Ÿฝโ€โ™€๏ธ', 'alice'], ['๐Ÿคต๐Ÿฝ', 'alice'], ['๐Ÿคต๐Ÿฝโ€โ™‚๏ธ', 'alice'], ['๐Ÿ‘ธ๐Ÿฝ', 'alice'], ['๐Ÿซ…๐Ÿฝ', 'alice'], ['๐Ÿคด๐Ÿฝ', 'alice'], ['๐Ÿฅท๐Ÿฝ', 'alice'], ['๐Ÿฆธ๐Ÿฝโ€โ™€๏ธ', 'alice'], ['๐Ÿฆธ๐Ÿฝ', 'alice'], ['๐Ÿฆธ๐Ÿฝโ€โ™‚๏ธ', 'alice'], ['๐Ÿฆน๐Ÿฝโ€โ™€๏ธ', 'alice'], ['๐Ÿฆน๐Ÿฝ', 'alice'], ['๐Ÿฆน๐Ÿฝโ€โ™‚๏ธ', 'alice'], ['๐Ÿคถ๐Ÿฝ', 'alice'], ['๐Ÿง‘๐Ÿฝโ€๐ŸŽ„', 'alice'], ['๐ŸŽ…๐Ÿฝ', 'alice'], ['๐Ÿง™๐Ÿฝโ€โ™€๏ธ', 'alice'], ['๐Ÿง™๐Ÿฝ', 'alice'], ['๐Ÿง™๐Ÿฝโ€โ™‚๏ธ', 'alice'], ['๐Ÿง๐Ÿฝโ€โ™€๏ธ', 'alice'], ['๐Ÿง๐Ÿฝ', 'alice'], ['๐Ÿง๐Ÿฝโ€โ™‚๏ธ', 'alice'], ['๐Ÿง›๐Ÿฝโ€โ™€๏ธ', 'alice'], ['๐Ÿง›๐Ÿฝ', 'alice'], ['๐Ÿง›๐Ÿฝโ€โ™‚๏ธ', 'alice'], ['๐Ÿงœ๐Ÿฝโ€โ™€๏ธ', 'alice'], ['๐Ÿงœ๐Ÿฝ', 'alice'], ['๐Ÿงœ๐Ÿฝโ€โ™‚๏ธ', 'alice'], ['๐Ÿงš๐Ÿฝโ€โ™€๏ธ', 'alice'], ['๐Ÿงš๐Ÿฝ', 'alice'], ['๐Ÿงš๐Ÿฝโ€โ™‚๏ธ', 'alice'], ['๐Ÿ‘ผ๐Ÿฝ', 'alice'], ['๐Ÿคฐ๐Ÿฝ', 'alice'], ['๐Ÿซ„๐Ÿฝ', 'alice'], ['๐Ÿซƒ๐Ÿฝ', 'alice'], ['๐Ÿคฑ๐Ÿฝ', 'alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿผ', 'alice'], ['๐Ÿง‘๐Ÿฝโ€๐Ÿผ', 'alice'], ['๐Ÿ‘จ๐Ÿฝโ€๐Ÿผ', 'alice'], ['๐Ÿ™‡๐Ÿฝโ€โ™€๏ธ', 'alice'], ['๐Ÿ™‡๐Ÿฝ', 'alice'], ['๐Ÿ™‡๐Ÿฝโ€โ™‚๏ธ', 'alice'], ['๐Ÿ’๐Ÿฝโ€โ™€๏ธ', 'alice'], ['๐Ÿ’๐Ÿฝ', 'alice'], ['๐Ÿ’๐Ÿฝโ€โ™‚๏ธ', 'alice'], ['๐Ÿ™…๐Ÿฝโ€โ™€๏ธ', 'alice'], ['๐Ÿ™…๐Ÿฝ', 'alice'], ['๐Ÿ™…๐Ÿฝโ€โ™‚๏ธ', 'alice'], ['๐Ÿ™†๐Ÿฝโ€โ™€๏ธ', 'alice'], ['๐Ÿ™†๐Ÿฝ', 'alice'], ['๐Ÿ™†๐Ÿฝโ€โ™‚๏ธ', 'alice'], ['๐Ÿ™‹๐Ÿฝโ€โ™€๏ธ', 'alice'], ['๐Ÿ™‹๐Ÿฝ', 'alice'], ['๐Ÿ™‹๐Ÿฝโ€โ™‚๏ธ', 'alice'], ['๐Ÿง๐Ÿฝโ€โ™€๏ธ', 'alice'], ['๐Ÿง๐Ÿฝ', 'alice'], ['๐Ÿง๐Ÿฝโ€โ™‚๏ธ', 'alice'], ['๐Ÿคฆ๐Ÿฝโ€โ™€๏ธ', 'alice'], ['๐Ÿคฆ๐Ÿฝ', 'alice'], ['๐Ÿคฆ๐Ÿฝโ€โ™‚๏ธ', 'alice'], ['๐Ÿคท๐Ÿฝโ€โ™€๏ธ', 'alice'], ['๐Ÿคท๐Ÿฝ', 'alice'], ['๐Ÿคท๐Ÿฝโ€โ™‚๏ธ', 'alice'], ['๐Ÿ™Ž๐Ÿฝโ€โ™€๏ธ', 'alice'], ['๐Ÿ™Ž๐Ÿฝ', 'alice'], ['๐Ÿ™Ž๐Ÿฝโ€โ™‚๏ธ', 'alice'], ['๐Ÿ™๐Ÿฝโ€โ™€๏ธ', 'alice'], ['๐Ÿ™๐Ÿฝ', 'alice'], ['๐Ÿ™๐Ÿฝโ€โ™‚๏ธ', 'alice'], ['๐Ÿ’‡๐Ÿฝโ€โ™€๏ธ', 'alice'], ['๐Ÿ’‡๐Ÿฝ', 'alice'], ['๐Ÿ’‡๐Ÿฝโ€โ™‚๏ธ', 'alice'], ['๐Ÿ’†๐Ÿฝโ€โ™€๏ธ', 'alice'], ['๐Ÿ’†๐Ÿฝ', 'alice'], ['๐Ÿ’†๐Ÿฝโ€โ™‚๏ธ', 'alice'], ['๐Ÿง–๐Ÿฝโ€โ™€๏ธ', 'alice'], ['๐Ÿง–๐Ÿฝ', 'alice'], ['๐Ÿง–๐Ÿฝโ€โ™‚๏ธ', 'alice'], ['๐Ÿ’ƒ๐Ÿฝ', 'alice'], ['๐Ÿ•บ๐Ÿฝ', 'alice'], ['๐Ÿ•ด๐Ÿฝ', 'alice'], ['๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿฆฝ', 'alice'], ['๐Ÿง‘๐Ÿฝโ€๐Ÿฆฝ', 'alice'], ], ], ]; } /** * @dataProvider providerTestRetrieveAllReactionsWithSpecificReaction */ public function testRetrieveAllReactionsWithSpecificReaction(array $comments, string $reaction, array $expected): void { $this->skipIfNotSupport4ByteUTF(); $manager = $this->getManager(); $processedComments = $this->proccessComments($comments); $comment = reset($processedComments); $all = $manager->retrieveAllReactionsWithSpecificReaction($comment->getId(), $reaction); $actual = array_map(function ($row) { return [ 'message' => $row->getMessage(), 'actorId' => $row->getActorId(), ]; }, $all); $this->assertEqualsCanonicalizing($expected, $actual); } public function providerTestRetrieveAllReactionsWithSpecificReaction(): array { return [ [ [ ['message', 'alice', 'comment', null], ], '๐Ÿ‘Ž', [], ], [ [ ['message', 'alice', 'comment', null], ['๐Ÿ‘', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘', 'frank', 'reaction', 'message#alice'], ], '๐Ÿ‘', [ ['๐Ÿ‘', 'alice'], ['๐Ÿ‘', 'frank'], ], ], [ [ ['message', 'alice', 'comment', null], ['๐Ÿ‘', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘Ž', 'alice', 'reaction', 'message#alice'], ['๐Ÿ‘', 'frank', 'reaction', 'message#alice'], ], '๐Ÿ‘Ž', [ ['๐Ÿ‘Ž', 'alice'], ], ], ]; } /** * @dataProvider providerTestGetReactionComment */ public function testGetReactionComment(array $comments, array $expected, bool $notFound): void { $this->skipIfNotSupport4ByteUTF(); $manager = $this->getManager(); $processedComments = $this->proccessComments($comments); $keys = ['message', 'actorId', 'verb', 'parent']; $expected = array_combine($keys, $expected); if ($notFound) { $this->expectException(\OCP\Comments\NotFoundException::class); } $comment = $processedComments[$expected['message'] . '#' . $expected['actorId']]; $actual = $manager->getReactionComment($comment->getParentId(), $comment->getActorType(), $comment->getActorId(), $comment->getMessage()); if (!$notFound) { $this->assertEquals($expected['message'], $actual->getMessage()); $this->assertEquals($expected['actorId'], $actual->getActorId()); $this->assertEquals($expected['verb'], $actual->getVerb()); $this->assertEquals($processedComments[$expected['parent']]->getId(), $actual->getParentId()); } } public function providerTestGetReactionComment(): array { return [ [ [ ['message', 'Matthew', 'comment', null], ['๐Ÿ‘', 'Matthew', 'reaction', 'message#Matthew'], ['๐Ÿ‘', 'Mark', 'reaction', 'message#Matthew'], ['๐Ÿ‘', 'Luke', 'reaction', 'message#Matthew'], ['๐Ÿ‘', 'John', 'reaction', 'message#Matthew'], ], ['๐Ÿ‘', 'Matthew', 'reaction', 'message#Matthew'], false, ], [ [ ['message', 'Matthew', 'comment', null], ['๐Ÿ‘', 'Matthew', 'reaction', 'message#Matthew'], ['๐Ÿ‘', 'Mark', 'reaction', 'message#Matthew'], ['๐Ÿ‘', 'Luke', 'reaction', 'message#Matthew'], ['๐Ÿ‘', 'John', 'reaction', 'message#Matthew'], ], ['๐Ÿ‘', 'Mark', 'reaction', 'message#Matthew'], false, ], [ [ ['message', 'Matthew', 'comment', null], ['๐Ÿ‘Ž', 'Matthew', 'reaction', 'message#Matthew'], ], ['๐Ÿ‘Ž', 'Matthew', 'reaction', 'message#Matthew'], false, ], [ [ ['message', 'Matthew', 'comment', null], ['๐Ÿ‘Ž', 'Matthew', 'reaction', 'message#Matthew'], ['๐Ÿ‘Ž', 'Matthew', 'reaction_deleted', 'message#Matthew'], ], ['๐Ÿ‘Ž', 'Matthew', 'reaction', 'message#Matthew'], true, ], ]; } /** * @dataProvider providerTestReactionMessageSize */ public function testReactionMessageSize($reactionString, $valid): void { $this->skipIfNotSupport4ByteUTF(); if (!$valid) { $this->expectException(\UnexpectedValueException::class); } $manager = $this->getManager(); $comment = new Comment(); $comment->setMessage($reactionString) ->setVerb('reaction') ->setActor('users', 'alice') ->setObject('files', 'file64'); $status = $manager->save($comment); $this->assertTrue($status); } public function providerTestReactionMessageSize(): array { return [ ['a', false], ['1', false], ['๐Ÿ‘', true], ['๐Ÿ‘๐Ÿ‘', false], ['๐Ÿ‘๐Ÿฝ', true], ['๐Ÿ‘จ๐Ÿฝโ€๐Ÿ’ป', true], ['๐Ÿ‘จ๐Ÿฝโ€๐Ÿ’ป๐Ÿ‘', false], ]; } /** * @dataProvider providerTestReactionsSummarizeOrdered */ public function testReactionsSummarizeOrdered(array $comments, array $expected, bool $isFullMatch): void { $this->skipIfNotSupport4ByteUTF(); $manager = $this->getManager(); $processedComments = $this->proccessComments($comments); $comment = end($processedComments); $actual = $manager->get($comment->getParentId()); if ($isFullMatch) { $this->assertSame($expected, $actual->getReactions()); } else { $subResult = array_slice($actual->getReactions(), 0, count($expected)); $this->assertSame($expected, $subResult); } } public function providerTestReactionsSummarizeOrdered(): array { return [ [ [ ['message', 'alice', 'comment', null], ['๐Ÿ‘', 'alice', 'reaction', 'message#alice'], ], ['๐Ÿ‘' => 1], true, ], [ [ ['message', 'alice', 'comment', null], ['๐Ÿ‘Ž', 'John', 'reaction', 'message#alice'], ['๐Ÿ’ผ', 'Luke', 'reaction', 'message#alice'], ['๐Ÿ“‹', 'Luke', 'reaction', 'message#alice'], ['๐Ÿš€', 'Luke', 'reaction', 'message#alice'], ['๐Ÿ–ค', 'Luke', 'reaction', 'message#alice'], ['๐Ÿ˜œ', 'Luke', 'reaction', 'message#alice'], ['๐ŸŒ–', 'Luke', 'reaction', 'message#alice'], ['๐Ÿ’–', 'Luke', 'reaction', 'message#alice'], ['๐Ÿ“ฅ', 'Luke', 'reaction', 'message#alice'], ['๐Ÿ‰', 'Luke', 'reaction', 'message#alice'], ['โ˜•', 'Luke', 'reaction', 'message#alice'], ['๐Ÿ„', 'Luke', 'reaction', 'message#alice'], ['๐Ÿ•', 'Luke', 'reaction', 'message#alice'], ['๐Ÿˆ', 'Luke', 'reaction', 'message#alice'], ['๐Ÿ›‚', 'Luke', 'reaction', 'message#alice'], ['๐Ÿ•ธ', 'Luke', 'reaction', 'message#alice'], ['๐Ÿฐ', 'Luke', 'reaction', 'message#alice'], ['โš™๏ธ', 'Luke', 'reaction', 'message#alice'], ['๐Ÿšจ', 'Luke', 'reaction', 'message#alice'], ['๐Ÿ‘ฅ', 'Luke', 'reaction', 'message#alice'], ['๐Ÿ‘', 'Paul', 'reaction', 'message#alice'], ['๐Ÿ‘', 'Peter', 'reaction', 'message#alice'], ['๐Ÿ’œ', 'Matthew', 'reaction', 'message#alice'], ['๐Ÿ’œ', 'Mark', 'reaction', 'message#alice'], ['๐Ÿ’œ', 'Luke', 'reaction', 'message#alice'], ], [ '๐Ÿ’œ' => 3, '๐Ÿ‘' => 2, ], false, ], ]; } }