From 33edb1503a45c049eaaf7f8c9ccdbfba1e9b0d6c Mon Sep 17 00:00:00 2001 From: Joe Campo Date: Sat, 25 Jun 2022 08:33:24 -0400 Subject: [PATCH] Update parsing for new packet structures --- app/Actions/FetchChatRooms.php | 2 +- app/Actions/HandleChatPacket.php | 23 ++++++++++++++----- app/Enums/AtomPacket.php | 2 +- tests/Feature/FetchChatroomsTest.php | 4 ++-- tests/Feature/HandleChatPacketsTest.php | 22 +++++++++++++++++- tests/Feature/fixtures/chat_room.entrance.txt | 1 + tests/Feature/fixtures/chat_room.exit.txt | 1 + tests/Feature/fixtures/chat_room.joined.txt | 2 +- tests/Feature/fixtures/chat_room.message.txt | 2 +- tests/TestPacket.php | 4 ++-- 10 files changed, 48 insertions(+), 15 deletions(-) create mode 100644 tests/Feature/fixtures/chat_room.entrance.txt create mode 100644 tests/Feature/fixtures/chat_room.exit.txt diff --git a/app/Actions/FetchChatRooms.php b/app/Actions/FetchChatRooms.php index b043949..5d5ea29 100644 --- a/app/Actions/FetchChatRooms.php +++ b/app/Actions/FetchChatRooms.php @@ -52,7 +52,7 @@ private function parseChatrooms(): Collection ->filter(fn (Packet $packet) => str_contains($packet->toHex(), '0001000109032000620f13020102010a010101')) ->map(fn (Packet $packet) => substr($packet->toHex(), 66)) ->flatMap(function ($hex) { - preg_match_all('/06(\d{2,4})09(.*?)100b/', $hex, $output); + preg_match_all('/06(\d{2,4})09(.*?)0202010201020001/', $hex, $output); return collect($output[1])->zip($output[2])->toArray(); }) diff --git a/app/Actions/HandleChatPacket.php b/app/Actions/HandleChatPacket.php index c252b29..3d44cf4 100644 --- a/app/Actions/HandleChatPacket.php +++ b/app/Actions/HandleChatPacket.php @@ -50,7 +50,7 @@ private function parseInstantMessage(Packet $packet): void ->explode('|') ->map(fn (string $data) => hex2binary($data)); - with(new Builder, function (Builder $builder) use ($screenName, $message) { + with(new Builder(), function (Builder $builder) use ($screenName, $message) { $builder->setTitle('New Instant Message 💌'); $builder->addRow([ 'Screenname' => $screenName, @@ -65,9 +65,12 @@ private function parseInstantMessage(Packet $packet): void private function parsePeopleInRoom(Packet $packet): void { - $roomList = collect(explode('100b01010b0200011d000b01', $packet->toHex())) - ->splice(1) - ->map(fn (string $name) => hex2binary(substr($name, 2, hexdec(substr($name, 0, 2)) * 2))); + $roomList = str($packet->toHex()) + ->substr(268) + ->explode('100b01') + ->slice(0, -1) + ->map(fn ($packet) => substr($packet, 22)) + ->map(fn (string $name) => hex2binary(substr($name, 0, hexdec(substr($name, 0, 2)) * 2))); cache()->put('screen_name', $roomList->pop()); $this->console->setPrompt(cache('screen_name').': '); @@ -89,6 +92,7 @@ private function parseRoomMessage(Packet $packet): void return $data->replace('7f4f6e6c696e65486f73743a09', '0a4f6e6c696e65486f73743a20'); }) ->replaceLast('0000', '|') + ->replaceMatches('/0d(.*?)0d$/', '') ->explode('|') ->map(fn (string $data) => trim(utf8_encode(hex2binary($data)))); @@ -109,7 +113,7 @@ private function parseRoomMessage(Packet $packet): void private function parseEntrance(Packet $packet): void { - with(hex2binary(substr($packet->toHex(), 22, strlen($packet->toHex()) - 24)), function ($screenName) { + with($this->parseScreenNameFromEntranceorExit($packet), function ($screenName) { cache(['room_list' => cache('room_list')->push($screenName)->unique()]); $this->console->setAutocomplete(fn () => cache('room_list')->toArray()); @@ -119,7 +123,7 @@ private function parseEntrance(Packet $packet): void private function parseGoodbye(Packet $packet): void { - with(hex2binary(substr($packet->toHex(), 22, strlen($packet->toHex()) - 24)), function ($screenName) { + with($this->parseScreenNameFromEntranceorExit($packet), function ($screenName) { cache(['room_list' => cache('room_list')->reject(fn ($name) => $name === $screenName)]); $this->console->setAutocomplete(fn () => cache('room_list')->toArray()); @@ -127,6 +131,13 @@ private function parseGoodbye(Packet $packet): void }); } + private function parseScreenNameFromEntranceorExit(Packet $packet): string + { + return with($packet->toHex(), function (string $packet) { + return hex2binary(str($packet)->replaceMatches('/0d(.*?)0d$/', '')->substr(22, strlen($packet) - 24)); + }); + } + private function hasMention(string $message): bool { return count($this->mentions($message)) > 0; diff --git a/app/Enums/AtomPacket.php b/app/Enums/AtomPacket.php index 2e987a9..db254c5 100644 --- a/app/Enums/AtomPacket.php +++ b/app/Enums/AtomPacket.php @@ -11,5 +11,5 @@ enum AtomPacket: string { case INSTANT_MESSAGE = '11d00010a01010302010003030101030900000c00030700010a0100001500000a020114011d00010a01030114'; case INSTANT_MESSAGE_END = '0114017f011100011d00010a010002010120011d000012000d'; - case CHATROOM_LIST = '100b01010b0200011d000b01'; + case CHATROOM_LIST = '72440401075'; } diff --git a/tests/Feature/FetchChatroomsTest.php b/tests/Feature/FetchChatroomsTest.php index 2b44ece..6327be4 100644 --- a/tests/Feature/FetchChatroomsTest.php +++ b/tests/Feature/FetchChatroomsTest.php @@ -1,8 +1,8 @@ parseChatrooms()->toArray())->toBe([ ['people' => 0, 'name' => 'deadend'], - ['people' => 14, 'name' => 'Welcome'], + ['people' => 7, 'name' => 'Welcome'], ['people' => 0, 'name' => 'The 8-bit Guy'], ['people' => 0, 'name' => 'Tech Linked'], ['people' => 0, 'name' => 'Nostalgia Nerd'], diff --git a/tests/Feature/HandleChatPacketsTest.php b/tests/Feature/HandleChatPacketsTest.php index eced2e7..375bda3 100644 --- a/tests/Feature/HandleChatPacketsTest.php +++ b/tests/Feature/HandleChatPacketsTest.php @@ -9,7 +9,7 @@ HandleChatPacket::run($this->console, $packet); - expect($this->output)->toContain('GuestUUN, x0r, phantasm, Jason, GuestNQG, GuestNAF, ill, GuestPAO, GuestVR4, Tox, Wubbking, GuestMAS are currently in this room.'); + expect($this->output)->toContain('reaol, Shaolin, TommyD, Zip, GameHost, Godly, punk, Guest53 are currently in this room.'); }); it('can parse new messages in the chat room', function () { @@ -42,6 +42,26 @@ expect($this->output)->toContain("\e[42mjust\e[0m"); }); +it('can parse exit of a user to chat room', function () { + test()->startConsole(); + cache(['room_list' => collect()]); + $packet = Packet::make(test()->fixture('chat_room.exit')); + + HandleChatPacket::run($this->console, $packet); + + expect($this->output)->toContain("GuestBXB has left the room."); +}); + +it('can parse entrance of a user to chat room', function () { + test()->startConsole(); + cache(['room_list' => collect()]); + $packet = Packet::make(test()->fixture('chat_room.entrance')); + + HandleChatPacket::run($this->console, $packet); + + expect($this->output)->toContain("GuestBXB has entered the room."); +}); + it('can receive instant messages', function () { test()->startConsole(); diff --git a/tests/Feature/fixtures/chat_room.entrance.txt b/tests/Feature/fixtures/chat_room.entrance.txt new file mode 100644 index 0000000..4b36ed2 --- /dev/null +++ b/tests/Feature/fixtures/chat_room.entrance.txt @@ -0,0 +1 @@ +5a24fb000e28182043412047756573744258420d5a578a00032818240d \ No newline at end of file diff --git a/tests/Feature/fixtures/chat_room.exit.txt b/tests/Feature/fixtures/chat_room.exit.txt new file mode 100644 index 0000000..36e27d2 --- /dev/null +++ b/tests/Feature/fixtures/chat_room.exit.txt @@ -0,0 +1 @@ +5a132f000e1c142043422047756573744258420d5a99ce00031c14240d \ No newline at end of file diff --git a/tests/Feature/fixtures/chat_room.joined.txt b/tests/Feature/fixtures/chat_room.joined.txt index d04c1cb..1759189 100644 --- a/tests/Feature/fixtures/chat_room.joined.txt +++ b/tests/Feature/fixtures/chat_room.joined.txt @@ -1 +1 @@ -5a11c401b21913204154001b000100011b0103011604130000020f13010101090413000002010c010002010102011d00000701010014032001200109041300000201150757656c636f6d65010a01000200010202031f000100040f019f040700040602724404010757656c636f6d65040800000200011d000c010500000000010c000500000100010111000b00000b01057265616f6c100b01010b0200011d000b0108477565737455554e100b01010b0200011d000b0103783072100b01010b0200011d000b01087068616e7461736d100b01010b0200011d000b01054a61736f6e100b01010b0200011d000b010847756573744e5147100b01010b0200011d000b010847756573744e4146100b01010b0200011d000b0103696c6c100b01010b0200011d000b0108477565737450414f100b01010b0200011d000b01084775657374565234100b01010b0200011d000b0103546f78100b01010b0200011d000b0108577562626b696e67100b01010b0200011d000b010847756573744d4153100b01010b0200011d000b0108477565737431334d100b01010b0200011d00010a010002010182011d00011100011804000001020012000d \ No newline at end of file +5aa13f01571913204154001b000100011b0104011604130000020f13010101090413000002010c010002010102011d00000701010014032001200109041300000201150757656c636f6d65010a01000200010202031f000100040f019f040700040602724404010757656c636f6d65040800000200011d000c010500000000010c000500000100010111000b00000b01057265616f6c100b0101020201020b02000b01075368616f6c696e100b0102020201020b02000b0106546f6d6d7944100b0103020201020b02000b01035a6970100b0104020201020b02000b010847616d65486f7374100b0105020201020b02000b0105476f646c79100b0106020201020b02000b010470756e6b100b0107020201020b02000b010747756573743533100b0108020201020b02000b0108477565737447574e100b0109020201020b0200011d00010a010002010182011d00011100011804000001020012000d5aa8dc00031913240d \ No newline at end of file diff --git a/tests/Feature/fixtures/chat_room.message.txt b/tests/Feature/fixtures/chat_room.message.txt index bf16f90..e0f83c4 100644 --- a/tests/Feature/fixtures/chat_room.message.txt +++ b/tests/Feature/fixtures/chat_room.message.txt @@ -1 +1 @@ -5ae104002b1a14204142477565737432345000000074686973206973206a75737420612074657374206d6573736167650d \ No newline at end of file +5af52e002b261920414247756573744e560000000074686973206973206a75737420612074657374206d6573736167650d5a04ea00032619240d \ No newline at end of file diff --git a/tests/TestPacket.php b/tests/TestPacket.php index a7d01d5..af17597 100644 --- a/tests/TestPacket.php +++ b/tests/TestPacket.php @@ -7,9 +7,9 @@ enum TestPacket: string { case INIT_ACK_PACKET = '5ab71100037f7f240d'; - case AB_PACKET = '5ad3af00271a142041424775657374444438000000686579207768617420697320757020796f7520677579730d'; + case AB_PACKET = '5a4ea900122d1c204142477565737432000000000068690d'; case cQ_PACKET = '5ac20800197f7fa0635100200001000107040000000403010276620002000d'; - case CJ_AT_PACKET = '5a215a00b1161220415400180001000109032000620f13020102010a010101000a06300964656164656e64100b010101020001000b0631340957656c636f6d65100b010301020001001006300954686520382d62697420477579100b010401020001000e06300954656368204c696e6b6564100b01050102000100110630094e6f7374616c676961204e657264100b01060102000100070630094e657773100b0107010200011100011d0000070101000701020012000d'; + case CJ_AT_PACKET = '5a1cc200b0161220415400180001000109032000620f13020102010a010101000a06300964656164656e640202010201020001000a06370957656c636f6d650202010201020001001006300954686520382d626974204775790202010201020001000e06300954656368204c696e6b6564020201020102000100110630094e6f7374616c676961204e657264020201020102000100070630094e65777302020102010200011100011d0000070101000701020012000d5a3bed00031612240d'; case Dd_AT_PACKET = '5ab10a02eb101020415400110001000d040002320101001303200128010901010c010500000000000c000500000000a1011d000109013501000101102401011003010010040100100c0320001e1008015b10400105103a0320001e01000108190000101702371c100b010110270100010200011100010a01010114263c68313e57656c636f6d6520746f2052652d414f4c205b414c504841204f4e455d3c2f68313e01146f3c623e446973636c61696d65723c2f623e3a20576520617265206e6f742073656c6c696e6720616363657373206f722073656c6c696e6720612070726f647563743b20627574207261746865722075736572732061726520706c656467696e6720746f20737570706f72742074686501145f2070726f6a65637420616e6420696e2065786368616e676520776527726520726577617264696e67207468656d206279206c657474696e67207468656d207472792052452d414f4c20696e206561726c7920616c706861206163636573732e01142e3c62723e3c62723e596f752068617665206c6f6767656420696e2061732061204775657374213c62723e3c62723e01142a3c623e52652d414f4c3c2f623e20697320616e20414f4cae2073657276657220656d756c61746f72202d01145320776869636820747269657320746f2070726f7669646520616e20657870657269656e636520746861742077617320617661696c61626c6520647572696e6720746865203139393073272e3c62723e3c62723e011457417320612047756573742c20796f757220657870657269656e63652077696c6c206265206c696d6974656420746f206368617420726f6f6d7320616e64206d65737361676520626f617264732c20686f77657665722c2001145d796f752077696c6c206e6f7420626520616c6c6f77656420746f20706f7374206d6573736167657320746f2074686520626f617264732e2042757420796f752063616e20667265656c79206368617420696e20726f6f6d73213c62723e011d000111000010000002000d5a6d29020b1110204154001200010001090320001e010a010101144d3c62723e4b65657020696e206d696e642074686174207468652073657276657220697320696e20616e203c623e414c5048413c2f623e207374617465206f6620646576656c6f706d656e742c2001144d7768696368206d65616e73206e6f742065766572797468696e6720697320676f696e6720746f20776f726b20617320796f75206d61792065787065637420697420746f6f2e3c62723e3c62723e01144a446576656c6f706d656e74206973203c753e6f6e2d676f696e6720616e6420636f6e74696e756f75733c2f753e2c2069742074616b65732074696d6520746f2072657365617263682c200114276c6561726e2c20746573742c20616e6420696d706c656d656e7420746865206368616e67657320011439736f20706c6561736520686176652070617469656e747320616e6420656e6a6f79207768617420646f657320776f726b213c62723e3c62723e01143d53657276657220646576656c6f706d656e74206973203c753e6f6e2d676f696e6720616e6420636f6e74696e756f75732e3c2f753e3c62723e3c62723e0114553c623e52652d414f4c20697320696e206e6f2077617920616666696c6961746564207769746820416d6572696361204f6e6c696e65206f7220616e79206f6620697473207375627369646961726965732e3c2f623e011d000111000010000002000d5a0c680012121020415400140001000e0c0253430012000d'; case SC_AT_PACKET = '5a026f003d131120415400150001000d1a0001090320001e10180957656c636f6d652c200d1d000c0701010c46000c090101000a020114011401210c0601010111000d'; }