diff --git a/.prettierignore b/.prettierignore index b763c2dd..5f89231e 100644 --- a/.prettierignore +++ b/.prettierignore @@ -8,6 +8,7 @@ tests/snapshots/**/*.json # Ignore submodule files lib/*/ +!lib/twitch-eventsub-ws conan-pkgs/*/ cmake/sanitizers-cmake/ tools/crash-handler @@ -30,3 +31,6 @@ vcpkg_installed/ # Compile commands generated by CMake compile_commands.json + +# include files +*.inc diff --git a/CHANGELOG.md b/CHANGELOG.md index 372d4b43..3f830149 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,7 +25,7 @@ - Bugfix: Fixed search in emote popup not always working correctly. (#5946) - Bugfix: Fixed channel point redemptions with messages not showing up if PubSub is disconnected. (#5948) - Dev: Subscriptions to PubSub channel points redemption topics now use no auth token, making it continue to work during PubSub shutdown. (#5947) -- Dev: Add initial experimental EventSub support. (#5837, #5895, #5897, #5904, #5910, #5903, #5915, #5916, #5930, #5935, #5932, #5943) +- Dev: Add initial experimental EventSub support. (#5837, #5895, #5897, #5904, #5910, #5903, #5915, #5916, #5930, #5935, #5932, #5943, #5952) - Dev: Remove unneeded platform specifier for toasts. (#5914) - Dev: Highlight checks now use non-capturing groups for the boundaries. (#5784) - Dev: Removed unused PubSub whisper code. (#5898) diff --git a/CMakeLists.txt b/CMakeLists.txt index e8baf571..a31caad5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -232,7 +232,7 @@ if (BUILD_WITH_CRASHPAD) add_subdirectory("${CMAKE_SOURCE_DIR}/tools/crash-handler") endif() -add_subdirectory(lib/twitch-eventsub-ws EXCLUDE_FROM_ALL) +add_subdirectory(lib/twitch-eventsub-ws) # Used to provide a date of build in the About page (for nightly builds). Getting the actual time of # compilation in CMake is a more involved, as documented in https://stackoverflow.com/q/24292898. diff --git a/lib/twitch-eventsub-ws/CMakeLists.txt b/lib/twitch-eventsub-ws/CMakeLists.txt index 535eb7ba..32585f31 100644 --- a/lib/twitch-eventsub-ws/CMakeLists.txt +++ b/lib/twitch-eventsub-ws/CMakeLists.txt @@ -32,3 +32,12 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) include(cmake/GenerateJson.cmake) add_subdirectory(src) + +if(BUILD_TESTS) + enable_testing() + add_subdirectory(tests) +endif() + +if(BUILD_BENCHMARKS) + add_subdirectory(benchmarks) +endif() diff --git a/lib/twitch-eventsub-ws/benchmarks/CMakeLists.txt b/lib/twitch-eventsub-ws/benchmarks/CMakeLists.txt new file mode 100644 index 00000000..e86ba390 --- /dev/null +++ b/lib/twitch-eventsub-ws/benchmarks/CMakeLists.txt @@ -0,0 +1,28 @@ +project(twitch-eventsub-ws-benchmark) + +set(SOURCES + src/main.cpp + resources/bench.qrc + + src/parse.cpp +) + +add_executable(${PROJECT_NAME} ${SOURCES}) +add_sanitizers(${PROJECT_NAME}) + +target_link_libraries(${PROJECT_NAME} PRIVATE + twitch-eventsub-ws + benchmark::benchmark + Qt${MAJOR_QT_VERSION}::Core # for QFile +) + +set_target_properties(${PROJECT_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" + CXX_STANDARD 20 + AUTORCC ON +) + +if(MSVC) + target_compile_options(${PROJECT_NAME} PRIVATE /EHsc /bigobj) +endif() diff --git a/lib/twitch-eventsub-ws/benchmarks/resources/bench.qrc b/lib/twitch-eventsub-ws/benchmarks/resources/bench.qrc new file mode 100644 index 00000000..f8c78036 --- /dev/null +++ b/lib/twitch-eventsub-ws/benchmarks/resources/bench.qrc @@ -0,0 +1,5 @@ + + + messages.ndjson + + diff --git a/lib/twitch-eventsub-ws/benchmarks/resources/messages.ndjson b/lib/twitch-eventsub-ws/benchmarks/resources/messages.ndjson new file mode 100644 index 00000000..b000503f --- /dev/null +++ b/lib/twitch-eventsub-ws/benchmarks/resources/messages.ndjson @@ -0,0 +1,24 @@ +{"metadata":{"message_id":"e6095757-c068-4a97-b6b4-46cb45c8d507","message_type":"notification","message_timestamp":"2023-05-14T12:31:47.995298776Z","subscription_type":"channel.ban","subscription_version":"1"},"payload":{"subscription":{"id":"4aa632e0-fca3-590b-e981-bbd12abdb3fe","status":"enabled","type":"channel.ban","version":"1","condition":{"broadcaster_user_id":"74378979"},"transport":{"method":"websocket","session_id":"38de428e_b11f07be"},"created_at":"2023-05-20T12:30:55.518375571Z","cost":0},"event":{"banned_at":"2023-05-20T12:30:55.518375571Z","broadcaster_user_id":"74378979","broadcaster_user_login":"testBroadcaster","broadcaster_user_name":"testBroadcaster","ends_at":"2023-05-20T12:40:55.518375571Z","is_permanent":false,"moderator_user_id":"29024944","moderator_user_login":"CLIModerator","moderator_user_name":"CLIModerator","reason":"This is a test event","user_id":"40389552","user_login":"testFromUser","user_name":"testFromUser"}}} +{"metadata":{"message_id":"7d9daa03-06f0-43ef-94d8-b22e8662bb99","message_type":"notification","message_timestamp":"2024-05-14T12:31:47.995298776Z","subscription_type":"channel.chat.message","subscription_version":"1"},"payload":{"subscription":{"id":"0b7f3361-672b-4d39-b307-dd5b576c9b27","status":"enabled","type":"channel.chat.message","version":"1","condition":{"broadcaster_user_id":"1971641","user_id":"2914196"},"transport":{"method":"websocket","session_id":"AgoQHR3s6Mb4T8GFB1l3DlPfiRIGY2VsbC1h"},"created_at":"2023-11-06T18:11:47.492253549Z","cost":0},"event":{"broadcaster_user_id":"1971641","broadcaster_user_login":"streamer","broadcaster_user_name":"streamer","chatter_user_id":"4145994","chatter_user_login":"viewer32","chatter_user_name":"viewer32","message_id":"cc106a89-1814-919d-454c-f4f2f970aae7","message":{"text":"Hi chat","fragments":[{"type":"text","text":"Hi chat","cheermote":null,"emote":null,"mention":null}]},"color":"#00FF7F","badges":[{"set_id":"moderator","id":"1","info":""},{"set_id":"subscriber","id":"12","info":"16"},{"set_id":"sub-gifter","id":"1","info":""}],"message_type":"text","cheer":null,"reply":null,"channel_points_custom_reward_id":null,"source_broadcaster_user_id":"112233","source_broadcaster_user_login":"streamer33","source_broadcaster_user_name":"streamer33","source_message_id":"e03f6d5d-8ec8-4c63-b473-9e5fe61e289b","source_badges":[{"set_id":"subscriber","id":"3","info":"3"}]}}} +{"metadata":{"message_id":"7906227f-d95f-4ac7-b766-171b93023333","message_type":"notification","message_timestamp":"2024-05-14T12:31:47.995298776Z","subscription_type":"channel.chat.message","subscription_version":"1"},"payload":{"subscription":{"id":"0b7f3361-672b-4d39-b307-dd5b576c9b27","status":"enabled","type":"channel.chat.message","version":"1","condition":{"broadcaster_user_id":"1971641","user_id":"2914196"},"transport":{"method":"websocket","session_id":"AgoQHR3s6Mb4T8GFB1l3DlPfiRIGY2VsbC1h"},"created_at":"2023-11-06T18:11:47.492253549Z","cost":0},"event":{"broadcaster_user_id":"1971641","broadcaster_user_login":"streamer","broadcaster_user_name":"streamer","chatter_user_id":"4145994","chatter_user_login":"viewer32","chatter_user_name":"viewer32","message_id":"cc106a89-1814-919d-454c-f4f2f970aae7","message":{"text":"Hi chat","fragments":[{"type":"text","text":"Hi chat","cheermote":null,"emote":null,"mention":null}]},"color":"#00FF7F","badges":[{"set_id":"moderator","id":"1","info":""},{"set_id":"subscriber","id":"12","info":"16"},{"set_id":"sub-gifter","id":"1","info":""}],"message_type":"text","cheer":null,"reply":null,"channel_points_custom_reward_id":null,"source_broadcaster_user_id":null,"source_broadcaster_user_login":null,"source_broadcaster_user_name":null,"source_message_id":null,"source_badges":null}}} +{"metadata":{"message_id":"be5c6e89-13b4-48cf-ab04-f83ca62b0b57","message_type":"notification","message_timestamp":"2024-05-14T12:31:47.995298776Z","subscription_type":"channel.chat.notification","subscription_version":"1"},"payload":{"subscription":{"id":"dc1a3cfc-a930-4972-bf9e-0ffc4e7a8996","status":"enabled","type":"channel.chat.notification","version":"1","condition":{"broadcaster_user_id":"1971641","user_id":"2914196"},"transport":{"method":"websocket","session_id":"AgoQOtgGkFvXRlSkij343CndhIGY2VsbC1h"},"created_at":"2023-10-06T18:04:38.807682738Z","cost":0},"event":{"broadcaster_user_id":"1971641","broadcaster_user_login":"streamer","broadcaster_user_name":"streamer","chatter_user_id":"49912639","chatter_user_login":"viewer23","chatter_user_name":"viewer23","chatter_is_anonymous":false,"color":"","badges":[],"system_message":"viewer23 subscribed at Tier 1. They've subscribed for 10 months!","message_id":"d62235c8-47ff-a4f4--84e8-5a29a65a9c03","message":{"text":"","fragments":[]},"notice_type":"shared_chat_resub","sub":null,"resub":null,"sub_gift":null,"community_sub_gift":null,"gift_paid_upgrade":null,"prime_paid_upgrade":null,"pay_it_forward":null,"raid":null,"unraid":null,"announcement":null,"bits_badge_tier":null,"charity_donation":null,"shared_chat_sub":null,"shared_chat_resub":{"cumulative_months":10,"duration_months":0,"streak_months":null,"sub_tier":"1000","is_gift":false,"gifter_is_anonymous":null,"gifter_user_id":null,"gifter_user_name":null,"gifter_user_login":null},"shared_chat_sub_gift":null,"shared_chat_community_sub_gift":null,"shared_chat_gift_paid_upgrade":null,"shared_chat_prime_paid_upgrade":null,"shared_chat_pay_it_forward":null,"shared_chat_raid":null,"shared_chat_unraid":null,"shared_chat_announcement":null,"shared_chat_bits_badge_tier":null,"shared_chat_charity_donation":null,"source_broadcaster_user_id":"112233","source_broadcaster_user_login":"streamer33","source_broadcaster_user_name":"streamer33","source_message_id":"2be7193d-0366-4453-b6ec-b288ce9f2c39","source_badges":[{"set_id":"subscriber","id":"3","info":"3"}]}}} +{"metadata":{"message_id":"2246f78c-ce7b-4639-836b-d3bddc3f65ef","message_type":"notification","message_timestamp":"2024-05-14T12:31:47.995298776Z","subscription_type":"channel.chat.notification","subscription_version":"1"},"payload":{"subscription":{"id":"96f9a91e-f1e0-43af-82ac-a6e934778805","status":"enabled","type":"channel.chat.notification","version":"1","condition":{"broadcaster_user_id":"165080419","user_id":"27620241"},"transport":{"method":"websocket","session_id":"AgoQUlB8aB2SSsavWVfcs5ljnBIGY2VsbC1j"},"created_at":"2023-11-20T16:41:22.999246448Z","cost":0},"event":{"broadcaster_user_id":"165080419","broadcaster_user_login":"elraenn","broadcaster_user_name":"Elraenn","chatter_user_id":"425829220","chatter_user_login":"kecogluali5","chatter_user_name":"Kecogluali5","chatter_is_anonymous":false,"color":"#0000FF","badges":[{"set_id":"subscriber","id":"12","info":"12"}],"system_message":"Kecogluali5 is paying forward the Gift they got from CasinoZEBERUS to the community!","message_id":"573a20ff-8f88-499e-be2b-c7079eb76f6c","message":{"text":"","fragments":[]},"notice_type":"pay_it_forward","sub":null,"resub":null,"sub_gift":null,"community_sub_gift":null,"gift_paid_upgrade":null,"prime_paid_upgrade":null,"pay_it_forward":{"recipient_user_id":null,"recipient_user_name":null,"recipient_user_login":null,"gifter_is_anonymous":false,"gifter_user_id":"967793245","gifter_user_name":"CasinoZEBERUS","gifter_user_login":"casinozeberus"},"raid":null,"unraid":null,"announcement":null,"bits_badge_tier":null,"charity_donation":null}}} +{"metadata":{"message_id":"8425d945-1e15-4790-81b2-6366b20ef9c2","message_type":"notification","message_timestamp":"2024-05-14T12:31:47.995298776Z","subscription_type":"channel.chat.notification","subscription_version":"1"},"payload":{"subscription":{"id":"96f9a91e-f1e0-43af-82ac-a6e934778805","status":"enabled","type":"channel.chat.notification","version":"1","condition":{"broadcaster_user_id":"165080419","user_id":"27620241"},"transport":{"method":"websocket","session_id":"AgoQUlB8aB2SSsavWVfcs5ljnBIGY2VsbC1j"},"created_at":"2023-11-20T16:41:22.999246448Z","cost":0},"event":{"broadcaster_user_id":"165080419","broadcaster_user_login":"elraenn","broadcaster_user_name":"Elraenn","chatter_user_id":"735414451","chatter_user_login":"deniztony","chatter_user_name":"DenizTony","chatter_is_anonymous":false,"color":"#03FCFC","badges":[{"set_id":"subscriber","id":"3","info":"5"},{"set_id":"rplace-2023","id":"1","info":""}],"system_message":"DenizTony is paying forward the Gift they got from VikingHido to the community!","message_id":"3bc0badf-1d2c-45cd-8743-62ba2f41a2f6","message":{"text":"","fragments":[]},"notice_type":"pay_it_forward","sub":null,"resub":null,"sub_gift":null,"community_sub_gift":null,"gift_paid_upgrade":null,"prime_paid_upgrade":null,"pay_it_forward":{"recipient_user_id":null,"recipient_user_name":null,"recipient_user_login":null,"gifter_is_anonymous":false,"gifter_user_id":"446352253","gifter_user_name":"VikingHido","gifter_user_login":"vikinghido"},"raid":null,"unraid":null,"announcement":null,"bits_badge_tier":null,"charity_donation":null}}} +{"metadata":{"message_id":"f39c8d5c-c264-4850-8fc0-0e38d3bba36e","message_type":"notification","message_timestamp":"2024-05-14T12:31:47.995298776Z","subscription_type":"channel.chat.notification","subscription_version":"1"},"payload":{"subscription":{"id":"d46bb9d5-7b78-4495-a8f6-31e0bfe74422","status":"enabled","type":"channel.chat.notification","version":"1","condition":{"broadcaster_user_id":"67931625","user_id":"27620241"},"transport":{"method":"websocket","session_id":"AgoQUlB8aB2SSsavWVfcs5ljnBIGY2VsbC1j"},"created_at":"2023-11-20T16:41:21.3673997Z","cost":0},"event":{"broadcaster_user_id":"67931625","broadcaster_user_login":"amar","broadcaster_user_name":"Amar","chatter_user_id":"276319092","chatter_user_login":"baba_avil","chatter_user_name":"BaBa_Avil","chatter_is_anonymous":false,"color":"#9ACD32","badges":[{"set_id":"subscriber","id":"3","info":"4"},{"set_id":"premium","id":"1","info":""}],"system_message":"BaBa_Avil is paying forward the Gift they got from sarius05 to melizhr!","message_id":"1b1cf50d-d01b-4019-a564-cad2937bfeae","message":{"text":"","fragments":[]},"notice_type":"pay_it_forward","sub":null,"resub":null,"sub_gift":null,"community_sub_gift":null,"gift_paid_upgrade":null,"prime_paid_upgrade":null,"pay_it_forward":{"recipient_user_id":"924524794","recipient_user_name":"melizhr","recipient_user_login":"melizhr","gifter_is_anonymous":false,"gifter_user_id":"434322296","gifter_user_name":"sarius05","gifter_user_login":"sarius05"},"raid":null,"unraid":null,"announcement":null,"bits_badge_tier":null,"charity_donation":null}}} +{"metadata":{"message_id":"d624fc2a-3504-432a-acbb-78b47ae5d882","message_type":"notification","message_timestamp":"2024-05-14T12:31:47.995298776Z","subscription_type":"channel.chat.notification","subscription_version":"1"},"payload":{"subscription":{"id":"96f9a91e-f1e0-43af-82ac-a6e934778805","status":"enabled","type":"channel.chat.notification","version":"1","condition":{"broadcaster_user_id":"165080419","user_id":"27620241"},"transport":{"method":"websocket","session_id":"AgoQUlB8aB2SSsavWVfcs5ljnBIGY2VsbC1j"},"created_at":"2023-11-20T16:41:22.999246448Z","cost":0},"event":{"broadcaster_user_id":"1337","broadcaster_user_login":"Cool_User","broadcaster_user_name":"cool_user","chatter_user_id":"1234","chatter_user_login":"justinfan1","chatter_user_name":"justinfan1","chatter_is_anonymous":false,"color":"#03FCFC","badges":[{"set_id":"subscriber","id":"3","info":"5"},{"set_id":"rplace-2023","id":"1","info":""}],"system_message":"justinfan1 is paying forward the Gift they got from SomeoneElse to the community!","message_id":"3bc0badf-1d2c-45cd-8743-62ba2f411337","message":{"text":"","fragments":[]},"notice_type":"pay_it_forward","sub":null,"resub":null,"sub_gift":null,"community_sub_gift":null,"gift_paid_upgrade":null,"prime_paid_upgrade":null,"pay_it_forward":{"recipient_user_id":null,"recipient_user_name":null,"recipient_user_login":null,"gifter_is_anonymous":false,"gifter_user_id":"5678","gifter_user_name":"SomeoneElse","gifter_user_login":"someoneelse"},"raid":null,"unraid":null,"announcement":null,"bits_badge_tier":null,"charity_donation":null}}} +{"metadata":{"message_id":"333c1c6a-475f-4c7a-bb16-fe0ae443ac32","message_type":"notification","message_timestamp":"2024-05-14T12:31:47.995298776Z","subscription_type":"channel.chat.notification","subscription_version":"1"},"payload":{"subscription":{"id":"96f9a91e-f1e0-43af-82ac-a6e934771337","status":"enabled","type":"channel.chat.notification","version":"1","condition":{"broadcaster_user_id":"165081337","user_id":"27620241"},"transport":{"method":"websocket","session_id":"AgoQUlB8aB2SSsavWVfcs5ljnBIGY2Vs1337"},"created_at":"2023-11-20T16:41:22.999246448Z","cost":0},"event":{"broadcaster_user_id":"1337","broadcaster_user_login":"Cool_User","broadcaster_user_name":"cool_user","chatter_user_id":"5678","chatter_user_login":"someone1","chatter_user_name":"someone1","chatter_is_anonymous":false,"color":"","badges":[{"set_id":"subscriber","id":"2","info":"2"}],"system_message":"someone1 subscribed at Tier 1. They've subscribed for 2 months!","message_id":"101ab672-fcde-4d71-8011-ac2859786cea","message":{"text":"","fragments":[]},"notice_type":"resub","sub":null,"resub":{"cumulative_months":2,"duration_months":0,"streak_months":null,"sub_tier":"1000","is_prime":false,"is_gift":true,"gifter_is_anonymous":false,"gifter_user_id":"1234","gifter_user_name":"justinfan1","gifter_user_login":"justinfan1"},"sub_gift":null,"community_sub_gift":null,"gift_paid_upgrade":null,"prime_paid_upgrade":null,"pay_it_forward":null,"raid":null,"unraid":null,"announcement":null,"bits_badge_tier":null,"charity_donation":null}}} +{"metadata":{"message_id":"dad488f6-ee77-472c-a113-be158651a28e","message_type":"notification","message_timestamp":"2024-05-14T12:31:47.995298776Z","subscription_type":"channel.chat.notification","subscription_version":"1"},"payload":{"subscription":{"id":"f6b57ae8-add7-4faa-a396-4d6c87cb1337","status":"enabled","type":"channel.chat.notification","version":"1","condition":{"broadcaster_user_id":"1337","user_id":"27620241"},"transport":{"method":"websocket","session_id":"AgoQ_ZPE5-zrR2W3HJjkQxrFfxIGY2Vs1337"},"created_at":"2023-11-20T09:52:07.940291459Z","cost":0},"event":{"broadcaster_user_id":"1337","broadcaster_user_login":"cool_user","broadcaster_user_name":"Cool_User","chatter_user_id":null,"chatter_user_login":null,"chatter_user_name":null,"chatter_is_anonymous":true,"color":"","badges":[],"system_message":"An anonymous user is gifting 1 Tier 1 Subs to Cool_User's community!","message_id":"fa2135ca-34da-413f-1337-4efa3c9a6bac","message":{"text":"","fragments":[]},"notice_type":"community_sub_gift","sub":null,"resub":null,"sub_gift":null,"community_sub_gift":{"id":"12111455614691086753","total":1,"cumulative_total":null,"sub_tier":"1000"},"gift_paid_upgrade":null,"prime_paid_upgrade":null,"pay_it_forward":null,"raid":null,"unraid":null,"announcement":null,"bits_badge_tier":null,"charity_donation":null}}} +{"metadata":{"message_id":"8466103d-5c96-4a92-b6ae-8a1a5ab9d22b","message_type":"notification","message_timestamp":"2024-05-14T12:31:47.995298776Z","subscription_type":"channel.chat.notification","subscription_version":"1"},"payload":{"subscription":{"id":"2237f256-1b83-4ec9-956e-c3578925e8e6","status":"enabled","type":"channel.chat.notification","version":"1","condition":{"broadcaster_user_id":"67931625","user_id":"27620241"},"transport":{"method":"websocket","session_id":"AgoQuf4yiyFuTd64mlIG4zbSOxIGY2VsbC1j"},"created_at":"2023-11-19T22:08:49.127052362Z","cost":0},"event":{"broadcaster_user_id":"67931625","broadcaster_user_login":"amar","broadcaster_user_name":"Amar","chatter_user_id":"101572475","chatter_user_login":"justinfan","chatter_user_name":"justinfan","chatter_is_anonymous":false,"color":"#FA6E02","badges":[{"set_id":"moderator","id":"1","info":""},{"set_id":"subscriber","id":"48","info":"58"},{"set_id":"partner","id":"1","info":""}],"system_message":"justinfan subscribed at Tier 1. They've subscribed for 58 months!","message_id":"aaa15585-0f43-4c32-8c48-56d58e9567a7","message":{"text":"GIB MIR DEN POKAL","fragments":[{"type":"text","text":"GIB MIR DEN POKAL","cheermote":null,"emote":null,"mention":null}]},"notice_type":"resub","sub":null,"resub":{"cumulative_months":58,"duration_months":0,"streak_months":null,"sub_tier":"1000","is_prime":false,"is_gift":false,"gifter_is_anonymous":null,"gifter_user_id":null,"gifter_user_name":null,"gifter_user_login":null},"sub_gift":null,"community_sub_gift":null,"gift_paid_upgrade":null,"prime_paid_upgrade":null,"pay_it_forward":null,"raid":null,"unraid":null,"announcement":null,"bits_badge_tier":null,"charity_donation":null}}} +{"metadata":{"message_id":"0df6d3ca-ac07-461c-bd21-3340dc2b61c8","message_type":"notification","message_timestamp":"2024-05-14T12:31:47.995298776Z","subscription_type":"channel.chat.notification","subscription_version":"1"},"payload":{"subscription":{"id":"eebd50e7-2e58-4034-849b-d47e935632da5","status":"enabled","type":"channel.chat.notification","version":"1","condition":{"broadcaster_user_id":"1337","user_id":"27620241"},"transport":{"method":"websocket","session_id":"AgoQTaaaaaaaab2QtdG5r8vMSBIaaaaaaaaa"},"created_at":"2023-11-19T21:31:08.935820817Z","cost":0},"event":{"broadcaster_user_id":"1337","broadcaster_user_login":"cool_user","broadcaster_user_name":"Cool_User","chatter_user_id":"1234","chatter_user_login":"justinfan","chatter_user_name":"justinfan","chatter_is_anonymous":false,"color":"#E20072","badges":[{"set_id":"subscriber","id":"60","info":"65"},{"set_id":"twitchconAmsterdam2020","id":"1","info":""}],"system_message":"justinfan subscribed at Tier 1. They've subscribed for 65 months!","message_id":"5dfe4963-9db8-44a9-9f69-27452aaaaa30","message":{"text":"","fragments":[]},"notice_type":"resub","sub":null,"resub":{"cumulative_months":65,"duration_months":0,"streak_months":null,"sub_tier":"1000","is_prime":false,"is_gift":false,"gifter_is_anonymous":null,"gifter_user_id":null,"gifter_user_name":null,"gifter_user_login":null},"sub_gift":null,"community_sub_gift":null,"gift_paid_upgrade":null,"prime_paid_upgrade":null,"pay_it_forward":null,"raid":null,"unraid":null,"announcement":null,"bits_badge_tier":null,"charity_donation":null}}} +{"metadata":{"message_id":"ae24c14e-2e34-4d78-99b0-9c5586a47cd9","message_type":"notification","message_timestamp":"2024-05-14T12:31:47.995298776Z","subscription_type":"channel.chat.notification","subscription_version":"1"},"payload":{"subscription":{"id":"dc1a3cfc-a930-4972-bf9e-0ffc4e7a8996","status":"enabled","type":"channel.chat.notification","version":"1","condition":{"broadcaster_user_id":"1971641","user_id":"2914196"},"transport":{"method":"websocket","session_id":"AgoQOtgGkFvXRlSkij343CndhIGY2VsbC1h"},"created_at":"2023-10-06T18:04:38.807682738Z","cost":0},"event":{"broadcaster_user_id":"1971641","broadcaster_user_login":"streamer","broadcaster_user_name":"streamer","chatter_user_id":"49912639","chatter_user_login":"viewer23","chatter_user_name":"viewer23","chatter_is_anonymous":false,"color":"","badges":[],"system_message":"viewer23 subscribed at Tier 1. They've subscribed for 10 months!","message_id":"d62235c8-47ff-a4f4--84e8-5a29a65a9c03","message":{"text":"","fragments":[]},"notice_type":"resub","sub":null,"resub":{"cumulative_months":10,"duration_months":0,"streak_months":null,"sub_tier":"1000","is_gift":false,"gifter_is_anonymous":null,"gifter_user_id":null,"gifter_user_name":null,"gifter_user_login":null},"sub_gift":null,"community_sub_gift":null,"gift_paid_upgrade":null,"prime_paid_upgrade":null,"pay_it_forward":null,"raid":null,"unraid":null,"announcement":null,"bits_badge_tier":null,"charity_donation":null,"shared_chat_sub":null,"shared_chat_resub":null,"shared_chat_sub_gift":null,"shared_chat_community_sub_gift":null,"shared_chat_gift_paid_upgrade":null,"shared_chat_prime_paid_upgrade":null,"shared_chat_pay_it_forward":null,"shared_chat_raid":null,"shared_chat_announcement":null,"source_broadcaster_user_id":null,"source_broadcaster_user_login":null,"source_broadcaster_user_name":null,"source_message_id":null,"source_badges":null}}} +{"metadata":{"message_id":"bf6e248f-a523-4bf8-b215-ea1822e60223","message_type":"notification","message_timestamp":"2024-05-14T12:31:47.995298776Z","subscription_type":"channel.moderate","subscription_version":"2"},"payload":{"subscription":{"id":"86d99e53-2837-40cf-bc6e-c6e00698919c","status":"enabled","type":"channel.moderate","version":"2","condition":{"broadcaster_user_id":"11148817","moderator_user_id":"117166826"},"transport":{"method":"websocket","session_id":"AgoQZgfnyKxXQ32hpzCWF4aCGBIGY2VsbC1j"},"created_at":"2025-02-01T12:02:16.005321321Z","cost":0},"event":{"broadcaster_user_id":"11148817","broadcaster_user_login":"pajlada","broadcaster_user_name":"pajlada","source_broadcaster_user_id":null,"source_broadcaster_user_login":null,"source_broadcaster_user_name":null,"moderator_user_id":"11148817","moderator_user_login":"pajlada","moderator_user_name":"pajlada","action":"followers","followers":{"follow_duration_minutes":0},"slow":null,"vip":null,"unvip":null,"mod":null,"unmod":null,"ban":null,"unban":null,"timeout":null,"untimeout":null,"raid":null,"unraid":null,"delete":null,"automod_terms":null,"unban_request":null,"warn":null,"shared_chat_ban":null,"shared_chat_unban":null,"shared_chat_timeout":null,"shared_chat_untimeout":null,"shared_chat_delete":null}}} +{"metadata":{"message_id":"b3426fa4-f7b0-4d20-827f-f620d9b9bce0","message_type":"notification","message_timestamp":"2024-05-14T12:31:47.995298776Z","subscription_type":"channel.moderate","subscription_version":"2"},"payload":{"subscription":{"id":"86d99e53-2837-40cf-bc6e-c6e00698919c","status":"enabled","type":"channel.moderate","version":"2","condition":{"broadcaster_user_id":"11148817","moderator_user_id":"117166826"},"transport":{"method":"websocket","session_id":"AgoQZgfnyKxXQ32hpzCWF4aCGBIGY2VsbC1j"},"created_at":"2025-02-01T12:02:16.005321321Z","cost":0},"event":{"broadcaster_user_id":"11148817","broadcaster_user_login":"pajlada","broadcaster_user_name":"pajlada","source_broadcaster_user_id":null,"source_broadcaster_user_login":null,"source_broadcaster_user_name":null,"moderator_user_id":"11148817","moderator_user_login":"pajlada","moderator_user_name":"pajlada","action":"followersoff","followers":null,"slow":null,"vip":null,"unvip":null,"mod":null,"unmod":null,"ban":null,"unban":null,"timeout":null,"untimeout":null,"raid":null,"unraid":null,"delete":null,"automod_terms":null,"unban_request":null,"warn":null,"shared_chat_ban":null,"shared_chat_unban":null,"shared_chat_timeout":null,"shared_chat_untimeout":null,"shared_chat_delete":null}}} +{"metadata":{"message_id":"0a0741bb-eb9f-4337-9581-d088c2acc3b2","message_type":"notification","message_timestamp":"2024-05-14T12:31:47.995298776Z","subscription_type":"channel.moderate","subscription_version":"2"},"payload":{"subscription":{"id":"86d99e53-2837-40cf-bc6e-c6e00698919c","status":"enabled","type":"channel.moderate","version":"2","condition":{"broadcaster_user_id":"11148817","moderator_user_id":"117166826"},"transport":{"method":"websocket","session_id":"AgoQZgfnyKxXQ32hpzCWF4aCGBIGY2VsbC1j"},"created_at":"2025-02-01T12:02:16.005321321Z","cost":0},"event":{"broadcaster_user_id":"11148817","broadcaster_user_login":"pajlada","broadcaster_user_name":"pajlada","source_broadcaster_user_id":null,"source_broadcaster_user_login":null,"source_broadcaster_user_name":null,"moderator_user_id":"11148817","moderator_user_login":"pajlada","moderator_user_name":"pajlada","action":"followers","followers":{"follow_duration_minutes":10080},"slow":null,"vip":null,"unvip":null,"mod":null,"unmod":null,"ban":null,"unban":null,"timeout":null,"untimeout":null,"raid":null,"unraid":null,"delete":null,"automod_terms":null,"unban_request":null,"warn":null,"shared_chat_ban":null,"shared_chat_unban":null,"shared_chat_timeout":null,"shared_chat_untimeout":null,"shared_chat_delete":null}}} +{"metadata":{"message_id":"c5c679a1-f99d-4863-9f57-c434b10dc39d","message_type":"notification","message_timestamp":"2024-05-14T12:31:47.995298776Z","subscription_type":"channel.moderate","subscription_version":"2"},"payload":{"subscription":{"id":"7297f7eb-3bf5-461f-8ae6-7cd7781ebce3","status":"enabled","type":"channel.moderate","version":"2","cost":0,"condition":{"broadcaster_user_id":"423374343","moderator_user_id":"423374343"},"transport":{"method":"websocket","session_id":"AgoQUlB8aB2SSsavWVfcs5ljnBIGY2VsbC1j"},"created_at":"2024-02-23T21:12:33.771005262Z"},"event":{"broadcaster_user_id":"423374343","broadcaster_user_login":"glowillig","broadcaster_user_name":"glowillig","moderator_user_id":"424596340","moderator_user_login":"quotrok","moderator_user_name":"quotrok","action":"emoteonly","followers":null,"slow":null,"vip":null,"unvip":null,"mod":null,"unmod":null,"ban":null,"unban":null,"warn":null,"timeout":null,"untimeout":null,"raid":null,"unraid":null,"delete":null,"automod_terms":null,"unban_request":null,"shared_chat_ban":null,"shared_chat_unban":null,"shared_chat_timeout":null,"shared_chat_untimeout":null,"shared_chat_delete":null}}} +{"metadata":{"message_id":"cf0534f2-a006-4c83-a958-346333bb631f","message_type":"notification","message_timestamp":"2024-05-14T12:31:47.995298776Z","subscription_type":"channel.moderate","subscription_version":"2"},"payload":{"subscription":{"id":"7297f7eb-3bf5-461f-8ae6-7cd7781ebce3","status":"enabled","type":"channel.moderate","version":"2","cost":0,"condition":{"broadcaster_user_id":"423374343","moderator_user_id":"423374343"},"transport":{"method":"websocket","session_id":"AgoQUlB8aB2SSsavWVfcs5ljnBIGY2VsbC1j"},"created_at":"2024-02-23T21:12:33.771005262Z"},"event":{"broadcaster_user_id":"423374343","broadcaster_user_login":"glowillig","broadcaster_user_name":"glowillig","moderator_user_id":"424596340","moderator_user_login":"quotrok","moderator_user_name":"quotrok","action":"mod","followers":null,"slow":null,"vip":null,"unvip":null,"warn":null,"mod":{"user_id":"141981764","user_login":"twitchdev","user_name":"TwitchDev"},"unmod":null,"ban":null,"unban":null,"timeout":null,"untimeout":null,"raid":null,"unraid":null,"delete":null,"automod_terms":null,"unban_request":null,"shared_chat_ban":null,"shared_chat_unban":null,"shared_chat_timeout":null,"shared_chat_untimeout":null,"shared_chat_delete":null}}} +{"metadata":{"message_id":"e8edc592-5550-4aa5-bba6-39e31a2be435","message_type":"notification","message_timestamp":"2024-05-14T12:31:47.995298776Z","subscription_type":"channel.moderate","subscription_version":"2"},"payload":{"subscription":{"id":"7297f7eb-3bf5-461f-8ae6-7cd7781ebce3","status":"enabled","type":"channel.moderate","version":"2","cost":0,"condition":{"broadcaster_user_id":"423374343","moderator_user_id":"424596340"},"transport":{"method":"websocket","session_id":"AgoQUlB8aB2SSsavWVfcs5ljnBIGY2VsbC1j"},"created_at":"2024-02-23T21:12:33.771005262Z"},"event":{"broadcaster_user_id":"423374343","broadcaster_user_login":"glowillig","broadcaster_user_name":"glowillig","source_broadcaster_user_id":"41292030","source_broadcaster_user_login":"adflynn404","source_broadcaster_user_name":"adflynn404","moderator_user_id":"424596340","moderator_user_login":"quotrok","moderator_user_name":"quotrok","action":"warn","followers":null,"slow":null,"vip":null,"unvip":null,"warn":{"user_id":"141981764","user_login":"twitchdev","user_name":"TwitchDev","reason":"cut it out","chat_rules_cited":null},"unmod":null,"ban":null,"unban":null,"timeout":null,"untimeout":null,"raid":null,"unraid":null,"delete":null,"automod_terms":null,"unban_request":null,"shared_chat_ban":null,"shared_chat_unban":null,"shared_chat_timeout":null,"shared_chat_untimeout":null,"shared_chat_delete":null}}} +{"metadata":{"message_id":"2ea469a5-4bc8-4f95-ae08-c10b679cf038","message_type":"notification","message_timestamp":"2024-05-14T12:31:47.995298776Z","subscription_type":"channel.moderate","subscription_version":"2"},"payload":{"subscription":{"id":"5a893cd8-c10e-4198-a620-e9f35fd6ccd6","status":"enabled","type":"channel.moderate","version":"2","condition":{"broadcaster_user_id":"129546453","moderator_user_id":"129546453"},"transport":{"method":"websocket","session_id":"AgoQMmDnfVEhRI6iLiBniEWHkxIGY2VsbC1j"},"created_at":"2024-11-27T20:01:50.171283653Z","cost":0},"event":{"broadcaster_user_id":"129546453","broadcaster_user_login":"nerixyz","broadcaster_user_name":"nerixyz","source_broadcaster_user_id":null,"source_broadcaster_user_login":null,"source_broadcaster_user_name":null,"moderator_user_id":"129546453","moderator_user_login":"nerixyz","moderator_user_name":"nerixyz","action":"timeout","followers":null,"slow":null,"vip":null,"unvip":null,"mod":null,"unmod":null,"ban":null,"unban":null,"timeout":{"user_id":"141981764","user_login":"twitchdev","user_name":"TwitchDev","reason":"test Kappa","expires_at":"2024-11-27T20:01:55.358149527Z"},"untimeout":null,"raid":null,"unraid":null,"delete":null,"automod_terms":null,"unban_request":null,"warn":null,"shared_chat_ban":null,"shared_chat_unban":null,"shared_chat_timeout":null,"shared_chat_untimeout":null,"shared_chat_delete":null}}} +{"metadata":{"message_id":"beb72a37-0c04-4d7e-9934-f611ddc0e869","message_type":"notification","message_timestamp":"2024-05-14T12:31:47.995298776Z","subscription_type":"channel.update","subscription_version":"1"},"payload":{"subscription":{"id":"f1c2a387-161a-49f9-a165-0f21d7a4e1c4","type":"channel.update","version":"1","status":"enabled","cost":0,"condition":{"broadcaster_user_id":"1337"},"transport":{"method":"websocket","session_id":"AgoQUlB8aB2SSsavWVfcs5ljnBIGY2VsbC1j"},"created_at":"2019-11-16T10:11:12.123Z"},"event":{"broadcaster_user_id":"1337","broadcaster_user_login":"cool_user","broadcaster_user_name":"Cool_User","title":"Best Stream Ever","language":"en","category_id":"21779","category_name":"Fortnite","is_mature":false}}} +{"metadata":{"message_id":"ee312d92-d9bb-4d4f-9e94-3a5e051940f3","message_type":"notification","message_timestamp":"2024-05-14T12:31:47.995298776Z","subscription_type":"stream.offline","subscription_version":"1"},"payload":{"subscription":{"id":"f1c2a387-161a-49f9-a165-0f21d7a4e1c4","type":"stream.offline","version":"1","status":"enabled","cost":0,"condition":{"broadcaster_user_id":"1337"},"created_at":"2019-11-16T10:11:12.123Z","transport":{"method":"websocket","session_id":"AgoQUlB8aB2SSsavWVfcs5ljnBIGY2VsbC1j"}},"event":{"broadcaster_user_id":"1337","broadcaster_user_login":"cool_user","broadcaster_user_name":"Cool_User"}}} +{"metadata":{"message_id":"ecaf20f2-6b08-4a17-ba14-581130d93c95","message_type":"notification","message_timestamp":"2024-05-14T12:31:47.995298776Z","subscription_type":"stream.online","subscription_version":"1"},"payload":{"subscription":{"id":"f1c2a387-161a-49f9-a165-0f21d7a4e1c4","type":"stream.online","version":"1","status":"enabled","cost":0,"condition":{"broadcaster_user_id":"1337"},"transport":{"method":"websocket","session_id":"AgoQUlB8aB2SSsavWVfcs5ljnBIGY2VsbC1j"},"created_at":"2019-11-16T10:11:12.123Z"},"event":{"id":"9001","broadcaster_user_id":"1337","broadcaster_user_login":"cool_user","broadcaster_user_name":"Cool_User","type":"live","started_at":"2020-10-11T10:11:12.123Z"}}} +{"metadata":{"message_id":"faf21c17-82d3-4479-8daa-295f16b706f0","message_type":"session_welcome","message_timestamp":"2023-07-19T14:56:51.634234626Z"},"payload":{"session":{"id":"AQoQILE98gtqShGmLD7AM6yJThAB","status":"connected","connected_at":"2023-07-19T14:56:51.616329898Z","keepalive_timeout_seconds":10,"reconnect_url":null}}} diff --git a/lib/twitch-eventsub-ws/benchmarks/src/main.cpp b/lib/twitch-eventsub-ws/benchmarks/src/main.cpp new file mode 100644 index 00000000..71fefa04 --- /dev/null +++ b/lib/twitch-eventsub-ws/benchmarks/src/main.cpp @@ -0,0 +1,3 @@ +#include + +BENCHMARK_MAIN(); diff --git a/lib/twitch-eventsub-ws/benchmarks/src/parse.cpp b/lib/twitch-eventsub-ws/benchmarks/src/parse.cpp new file mode 100644 index 00000000..5941b8f7 --- /dev/null +++ b/lib/twitch-eventsub-ws/benchmarks/src/parse.cpp @@ -0,0 +1,130 @@ +#include "twitch-eventsub-ws/listener.hpp" +#include "twitch-eventsub-ws/session.hpp" + +#include +#include +#include + +#include + +namespace { + +using namespace chatterino::eventsub::lib; + +std::vector readMessages() +{ + QFile file(":/bench/messages.ndjson"); + assert(file.open(QFile::ReadOnly)); + + std::vector messages; + while (!file.atEnd()) + { + QByteArray line = file.readLine(); + if (line.isEmpty()) + { + continue; + } + + boost::beast::flat_buffer buf; + auto inner = buf.prepare(line.size()); + std::memcpy(inner.data(), line.data(), inner.size()); + buf.commit(inner.size()); + + messages.emplace_back(std::move(buf)); + } + return messages; +} + +class NoopListener : public Listener +{ +public: + NoopListener() = default; + + // NOLINTBEGIN(cppcoreguidelines-pro-type-const-cast) + void onSessionWelcome(messages::Metadata metadata, + payload::session_welcome::Payload payload) override + { + benchmark::DoNotOptimize(&metadata); + benchmark::DoNotOptimize(&payload); + } + + void onNotification(messages::Metadata metadata, + const boost::json::value &jv) override + { + benchmark::DoNotOptimize(&metadata); + benchmark::DoNotOptimize(&jv); + } + + void onChannelBan(messages::Metadata metadata, + payload::channel_ban::v1::Payload payload) override + { + benchmark::DoNotOptimize(&metadata); + benchmark::DoNotOptimize(&payload); + } + + void onStreamOnline(messages::Metadata metadata, + payload::stream_online::v1::Payload payload) override + { + benchmark::DoNotOptimize(&metadata); + benchmark::DoNotOptimize(&payload); + } + + void onStreamOffline(messages::Metadata metadata, + payload::stream_offline::v1::Payload payload) override + { + benchmark::DoNotOptimize(&metadata); + benchmark::DoNotOptimize(&payload); + } + + void onChannelChatNotification( + messages::Metadata metadata, + payload::channel_chat_notification::v1::Payload payload) override + { + benchmark::DoNotOptimize(&metadata); + benchmark::DoNotOptimize(&payload); + } + + void onChannelUpdate(messages::Metadata metadata, + payload::channel_update::v1::Payload payload) override + { + benchmark::DoNotOptimize(&metadata); + benchmark::DoNotOptimize(&payload); + } + + void onChannelChatMessage( + messages::Metadata metadata, + payload::channel_chat_message::v1::Payload payload) override + { + benchmark::DoNotOptimize(&metadata); + benchmark::DoNotOptimize(&payload); + } + + void onChannelModerate( + messages::Metadata metadata, + payload::channel_moderate::v2::Payload payload) override + { + benchmark::DoNotOptimize(&metadata); + benchmark::DoNotOptimize(&payload); + } + // NOLINTEND(cppcoreguidelines-pro-type-const-cast) +}; + +void BM_ParseAndHandleMessages(benchmark::State &state) +{ + auto messages = readMessages(); + + std::unique_ptr listener = std::make_unique(); + + for (auto _ : state) + { + for (const auto &msg : messages) + { + boost::system::error_code ec = handleMessage(listener, msg); + assert(!ec); + } + } +} + +} // namespace + +BENCHMARK(BM_ParseAndHandleMessages); diff --git a/lib/twitch-eventsub-ws/include/twitch-eventsub-ws/payloads/channel-chat-notification-v1.hpp b/lib/twitch-eventsub-ws/include/twitch-eventsub-ws/payloads/channel-chat-notification-v1.hpp index 0a3cf9a4..d678a946 100644 --- a/lib/twitch-eventsub-ws/include/twitch-eventsub-ws/payloads/channel-chat-notification-v1.hpp +++ b/lib/twitch-eventsub-ws/include/twitch-eventsub-ws/payloads/channel-chat-notification-v1.hpp @@ -58,9 +58,9 @@ struct Resubscription { int durationMonths; std::optional streakMonths; std::string subTier; - bool isPrime; + std::optional isPrime; bool isGift; - bool gifterIsAnonymous; + std::optional gifterIsAnonymous; std::optional gifterUserID; std::optional gifterUserName; std::optional gifterUserLogin; @@ -162,9 +162,9 @@ struct Event { std::string broadcasterUserID; std::string broadcasterUserLogin; std::string broadcasterUserName; - std::string chatterUserID; - std::string chatterUserLogin; - std::string chatterUserName; + std::optional chatterUserID; + std::optional chatterUserLogin; + std::optional chatterUserName; bool chatterIsAnonymous; std::string color; std::vector badges; diff --git a/lib/twitch-eventsub-ws/src/generated/payloads/channel-chat-notification-v1.cpp b/lib/twitch-eventsub-ws/src/generated/payloads/channel-chat-notification-v1.cpp index e0f5c70f..d082a717 100644 --- a/lib/twitch-eventsub-ws/src/generated/payloads/channel-chat-notification-v1.cpp +++ b/lib/twitch-eventsub-ws/src/generated/payloads/channel-chat-notification-v1.cpp @@ -471,17 +471,17 @@ boost::json::result_for::type tag_invoke( static_assert(std::is_trivially_copyable_v().isPrime)>>); + std::optional isPrime = std::nullopt; const auto *jvisPrime = root.if_contains("is_prime"); - if (jvisPrime == nullptr) + if (jvisPrime != nullptr && !jvisPrime->is_null()) { - EVENTSUB_BAIL_HERE(error::Kind::FieldMissing); - } + auto tisPrime = boost::json::try_value_to(*jvisPrime); - auto isPrime = boost::json::try_value_to(*jvisPrime); - - if (isPrime.has_error()) - { - return isPrime.error(); + if (tisPrime.has_error()) + { + return tisPrime.error(); + } + isPrime = tisPrime.value(); } static_assert(std::is_trivially_copyable_v::type tag_invoke( static_assert( std::is_trivially_copyable_v().gifterIsAnonymous)>>); + std::optional gifterIsAnonymous = std::nullopt; const auto *jvgifterIsAnonymous = root.if_contains("gifter_is_anonymous"); - if (jvgifterIsAnonymous == nullptr) + if (jvgifterIsAnonymous != nullptr && !jvgifterIsAnonymous->is_null()) { - EVENTSUB_BAIL_HERE(error::Kind::FieldMissing); - } + auto tgifterIsAnonymous = + boost::json::try_value_to(*jvgifterIsAnonymous); - auto gifterIsAnonymous = - boost::json::try_value_to(*jvgifterIsAnonymous); - - if (gifterIsAnonymous.has_error()) - { - return gifterIsAnonymous.error(); + if (tgifterIsAnonymous.has_error()) + { + return tgifterIsAnonymous.error(); + } + gifterIsAnonymous = tgifterIsAnonymous.value(); } std::optional gifterUserID = std::nullopt; @@ -563,9 +563,9 @@ boost::json::result_for::type tag_invoke( .durationMonths = durationMonths.value(), .streakMonths = streakMonths, .subTier = std::move(subTier.value()), - .isPrime = isPrime.value(), + .isPrime = isPrime, .isGift = isGift.value(), - .gifterIsAnonymous = gifterIsAnonymous.value(), + .gifterIsAnonymous = gifterIsAnonymous, .gifterUserID = std::move(gifterUserID), .gifterUserName = std::move(gifterUserName), .gifterUserLogin = std::move(gifterUserLogin), @@ -1327,46 +1327,46 @@ boost::json::result_for::type tag_invoke( return broadcasterUserName.error(); } + std::optional chatterUserID = std::nullopt; const auto *jvchatterUserID = root.if_contains("chatter_user_id"); - if (jvchatterUserID == nullptr) + if (jvchatterUserID != nullptr && !jvchatterUserID->is_null()) { - EVENTSUB_BAIL_HERE(error::Kind::FieldMissing); - } - - auto chatterUserID = - boost::json::try_value_to(*jvchatterUserID); - - if (chatterUserID.has_error()) - { - return chatterUserID.error(); + auto tchatterUserID = + boost::json::try_value_to(*jvchatterUserID); + + if (tchatterUserID.has_error()) + { + return tchatterUserID.error(); + } + chatterUserID = std::move(tchatterUserID.value()); } + std::optional chatterUserLogin = std::nullopt; const auto *jvchatterUserLogin = root.if_contains("chatter_user_login"); - if (jvchatterUserLogin == nullptr) + if (jvchatterUserLogin != nullptr && !jvchatterUserLogin->is_null()) { - EVENTSUB_BAIL_HERE(error::Kind::FieldMissing); - } - - auto chatterUserLogin = - boost::json::try_value_to(*jvchatterUserLogin); - - if (chatterUserLogin.has_error()) - { - return chatterUserLogin.error(); + auto tchatterUserLogin = + boost::json::try_value_to(*jvchatterUserLogin); + + if (tchatterUserLogin.has_error()) + { + return tchatterUserLogin.error(); + } + chatterUserLogin = std::move(tchatterUserLogin.value()); } + std::optional chatterUserName = std::nullopt; const auto *jvchatterUserName = root.if_contains("chatter_user_name"); - if (jvchatterUserName == nullptr) + if (jvchatterUserName != nullptr && !jvchatterUserName->is_null()) { - EVENTSUB_BAIL_HERE(error::Kind::FieldMissing); - } + auto tchatterUserName = + boost::json::try_value_to(*jvchatterUserName); - auto chatterUserName = - boost::json::try_value_to(*jvchatterUserName); - - if (chatterUserName.has_error()) - { - return chatterUserName.error(); + if (tchatterUserName.has_error()) + { + return tchatterUserName.error(); + } + chatterUserName = std::move(tchatterUserName.value()); } static_assert(std::is_trivially_copyable_v::type tag_invoke( .broadcasterUserID = std::move(broadcasterUserID.value()), .broadcasterUserLogin = std::move(broadcasterUserLogin.value()), .broadcasterUserName = std::move(broadcasterUserName.value()), - .chatterUserID = std::move(chatterUserID.value()), - .chatterUserLogin = std::move(chatterUserLogin.value()), - .chatterUserName = std::move(chatterUserName.value()), + .chatterUserID = std::move(chatterUserID), + .chatterUserLogin = std::move(chatterUserLogin), + .chatterUserName = std::move(chatterUserName), .chatterIsAnonymous = chatterIsAnonymous.value(), .color = std::move(color.value()), .badges = std::move(vbadges), diff --git a/lib/twitch-eventsub-ws/src/session.cpp b/lib/twitch-eventsub-ws/src/session.cpp index 13f98ca3..a468d406 100644 --- a/lib/twitch-eventsub-ws/src/session.cpp +++ b/lib/twitch-eventsub-ws/src/session.cpp @@ -32,14 +32,15 @@ using EventSubSubscription = std::pair; using NotificationHandlers = std::unordered_map< EventSubSubscription, - std::function &)>, + std::function &)>, boost::hash>; -using MessageHandlers = std::unordered_map< - std::string, std::function &, - const NotificationHandlers &)>>; +using MessageHandlers = + std::unordered_map &, + const NotificationHandlers &)>>; namespace { @@ -51,13 +52,12 @@ namespace { } template - std::optional parsePayload(const boost::json::value &jv) + boost::system::result parsePayload(const boost::json::value &jv) { auto result = boost::json::try_value_to(jv); if (!result.has_value()) { - fail(result.error(), "parsing payload"); - return std::nullopt; + return result.error(); } return std::move(result.value()); @@ -72,9 +72,10 @@ namespace { parsePayload(jv); if (!oPayload) { - return; + return oPayload.error(); } listener->onChannelBan(metadata, *oPayload); + return boost::system::error_code{}; }, }, { @@ -84,9 +85,10 @@ namespace { parsePayload(jv); if (!oPayload) { - return; + return oPayload.error(); } listener->onStreamOnline(metadata, *oPayload); + return boost::system::error_code{}; }, }, { @@ -96,9 +98,10 @@ namespace { parsePayload(jv); if (!oPayload) { - return; + return oPayload.error(); } listener->onStreamOffline(metadata, *oPayload); + return boost::system::error_code{}; }, }, { @@ -108,9 +111,10 @@ namespace { payload::channel_chat_notification::v1::Payload>(jv); if (!oPayload) { - return; + return oPayload.error(); } listener->onChannelChatNotification(metadata, *oPayload); + return boost::system::error_code{}; }, }, { @@ -120,9 +124,10 @@ namespace { parsePayload(jv); if (!oPayload) { - return; + return oPayload.error(); } listener->onChannelUpdate(metadata, *oPayload); + return boost::system::error_code{}; }, }, { @@ -133,9 +138,10 @@ namespace { jv); if (!oPayload) { - return; + return oPayload.error(); } listener->onChannelChatMessage(metadata, *oPayload); + return boost::system::error_code{}; }, }, { @@ -145,9 +151,10 @@ namespace { parsePayload(jv); if (!oPayload) { - return; + return oPayload.error(); } listener->onChannelModerate(metadata, std::move(*oPayload)); + return boost::system::error_code{}; }, }, // Add your new subscription types above this line @@ -163,11 +170,12 @@ namespace { if (!oPayload) { // TODO: error handling - return; + return oPayload.error(); } const auto &payload = *oPayload; listener->onSessionWelcome(metadata, payload); + return boost::system::error_code{}; }, }, { @@ -175,6 +183,7 @@ namespace { [](const auto &metadata, const auto &jv, auto &listener, const auto ¬ificationHandlers) { // TODO: should we do something here? + return boost::system::error_code{}; }, }, { @@ -186,7 +195,7 @@ namespace { if (!metadata.subscriptionType || !metadata.subscriptionVersion) { // TODO: error handling - return; + return boost::system::error_code{}; } auto it = @@ -194,11 +203,10 @@ namespace { *metadata.subscriptionVersion}); if (it == notificationHandlers.end()) { - // TODO: error handling - return; + EVENTSUB_BAIL_HERE(error::Kind::NoMessageHandler); } - it->second(metadata, jv, listener); + return it->second(metadata, jv, listener); }, }, }; @@ -251,9 +259,8 @@ boost::system::error_code handleMessage(std::unique_ptr &listener, EVENTSUB_BAIL_HERE(error::Kind::FieldMissing); } - handler->second(metadata, *payloadV, listener, NOTIFICATION_HANDLERS); - - return {}; + return handler->second(metadata, *payloadV, listener, + NOTIFICATION_HANDLERS); } // Resolver and socket require an io_context @@ -396,7 +403,7 @@ void Session::onRead(beast::error_code ec, std::size_t bytes_transferred) auto messageError = handleMessage(this->listener, this->buffer); if (messageError) { - return fail(messageError, "handleMessage"); + fail(messageError, "handleMessage"); } this->buffer.clear(); diff --git a/lib/twitch-eventsub-ws/tests/CMakeLists.txt b/lib/twitch-eventsub-ws/tests/CMakeLists.txt new file mode 100644 index 00000000..c2289c65 --- /dev/null +++ b/lib/twitch-eventsub-ws/tests/CMakeLists.txt @@ -0,0 +1,23 @@ +project(twitch-eventsub-ws-test) + +set(SOURCES + src/parse.cpp +) + +add_executable(${PROJECT_NAME} ${SOURCES}) +add_sanitizers(${PROJECT_NAME}) + +target_link_libraries(${PROJECT_NAME} PRIVATE twitch-eventsub-ws GTest::gtest_main) + +set_target_properties(${PROJECT_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" + CXX_STANDARD 20 +) + +if(MSVC) + target_compile_options(${PROJECT_NAME} PRIVATE /EHsc /bigobj) +endif() + +include(GoogleTest) +gtest_discover_tests(${PROJECT_NAME}) diff --git a/lib/twitch-eventsub-ws/tests/resources/messages/channel.ban.json b/lib/twitch-eventsub-ws/tests/resources/messages/channel.ban.json new file mode 100644 index 00000000..51124911 --- /dev/null +++ b/lib/twitch-eventsub-ws/tests/resources/messages/channel.ban.json @@ -0,0 +1,36 @@ +{ + "metadata": { + "message_id": "e6095757-c068-4a97-b6b4-46cb45c8d507", + "message_type": "notification", + "message_timestamp": "2023-05-14T12:31:47.995298776Z", + "subscription_type": "channel.ban", + "subscription_version": "1" + }, + "payload": { + "subscription": { + "id": "4aa632e0-fca3-590b-e981-bbd12abdb3fe", + "status": "enabled", + "type": "channel.ban", + "version": "1", + "condition": { "broadcaster_user_id": "74378979" }, + "transport": { "method": "websocket", "session_id": "38de428e_b11f07be" }, + "created_at": "2023-05-20T12:30:55.518375571Z", + "cost": 0 + }, + "event": { + "banned_at": "2023-05-20T12:30:55.518375571Z", + "broadcaster_user_id": "74378979", + "broadcaster_user_login": "testBroadcaster", + "broadcaster_user_name": "testBroadcaster", + "ends_at": "2023-05-20T12:40:55.518375571Z", + "is_permanent": false, + "moderator_user_id": "29024944", + "moderator_user_login": "CLIModerator", + "moderator_user_name": "CLIModerator", + "reason": "This is a test event", + "user_id": "40389552", + "user_login": "testFromUser", + "user_name": "testFromUser" + } + } +} diff --git a/lib/twitch-eventsub-ws/tests/resources/messages/channel.chat.message.json b/lib/twitch-eventsub-ws/tests/resources/messages/channel.chat.message.json new file mode 100644 index 00000000..df47ad10 --- /dev/null +++ b/lib/twitch-eventsub-ws/tests/resources/messages/channel.chat.message.json @@ -0,0 +1,60 @@ +{ + "metadata": { + "message_id": "7d9daa03-06f0-43ef-94d8-b22e8662bb99", + "message_type": "notification", + "message_timestamp": "2024-05-14T12:31:47.995298776Z", + "subscription_type": "channel.chat.message", + "subscription_version": "1" + }, + "payload": { + "subscription": { + "id": "0b7f3361-672b-4d39-b307-dd5b576c9b27", + "status": "enabled", + "type": "channel.chat.message", + "version": "1", + "condition": { "broadcaster_user_id": "1971641", "user_id": "2914196" }, + "transport": { + "method": "websocket", + "session_id": "AgoQHR3s6Mb4T8GFB1l3DlPfiRIGY2VsbC1h" + }, + "created_at": "2023-11-06T18:11:47.492253549Z", + "cost": 0 + }, + "event": { + "broadcaster_user_id": "1971641", + "broadcaster_user_login": "streamer", + "broadcaster_user_name": "streamer", + "chatter_user_id": "4145994", + "chatter_user_login": "viewer32", + "chatter_user_name": "viewer32", + "message_id": "cc106a89-1814-919d-454c-f4f2f970aae7", + "message": { + "text": "Hi chat", + "fragments": [ + { + "type": "text", + "text": "Hi chat", + "cheermote": null, + "emote": null, + "mention": null + } + ] + }, + "color": "#00FF7F", + "badges": [ + { "set_id": "moderator", "id": "1", "info": "" }, + { "set_id": "subscriber", "id": "12", "info": "16" }, + { "set_id": "sub-gifter", "id": "1", "info": "" } + ], + "message_type": "text", + "cheer": null, + "reply": null, + "channel_points_custom_reward_id": null, + "source_broadcaster_user_id": "112233", + "source_broadcaster_user_login": "streamer33", + "source_broadcaster_user_name": "streamer33", + "source_message_id": "e03f6d5d-8ec8-4c63-b473-9e5fe61e289b", + "source_badges": [{ "set_id": "subscriber", "id": "3", "info": "3" }] + } + } +} diff --git a/lib/twitch-eventsub-ws/tests/resources/messages/channel.chat.notification-community-sub-gift.json b/lib/twitch-eventsub-ws/tests/resources/messages/channel.chat.notification-community-sub-gift.json new file mode 100644 index 00000000..dcf487f0 --- /dev/null +++ b/lib/twitch-eventsub-ws/tests/resources/messages/channel.chat.notification-community-sub-gift.json @@ -0,0 +1,56 @@ +{ + "metadata": { + "message_id": "dad488f6-ee77-472c-a113-be158651a28e", + "message_type": "notification", + "message_timestamp": "2024-05-14T12:31:47.995298776Z", + "subscription_type": "channel.chat.notification", + "subscription_version": "1" + }, + "payload": { + "subscription": { + "id": "f6b57ae8-add7-4faa-a396-4d6c87cb1337", + "status": "enabled", + "type": "channel.chat.notification", + "version": "1", + "condition": { "broadcaster_user_id": "1337", "user_id": "27620241" }, + "transport": { + "method": "websocket", + "session_id": "AgoQ_ZPE5-zrR2W3HJjkQxrFfxIGY2Vs1337" + }, + "created_at": "2023-11-20T09:52:07.940291459Z", + "cost": 0 + }, + "event": { + "broadcaster_user_id": "1337", + "broadcaster_user_login": "cool_user", + "broadcaster_user_name": "Cool_User", + "chatter_user_id": null, + "chatter_user_login": null, + "chatter_user_name": null, + "chatter_is_anonymous": true, + "color": "", + "badges": [], + "system_message": "An anonymous user is gifting 1 Tier 1 Subs to Cool_User's community!", + "message_id": "fa2135ca-34da-413f-1337-4efa3c9a6bac", + "message": { "text": "", "fragments": [] }, + "notice_type": "community_sub_gift", + "sub": null, + "resub": null, + "sub_gift": null, + "community_sub_gift": { + "id": "12111455614691086753", + "total": 1, + "cumulative_total": null, + "sub_tier": "1000" + }, + "gift_paid_upgrade": null, + "prime_paid_upgrade": null, + "pay_it_forward": null, + "raid": null, + "unraid": null, + "announcement": null, + "bits_badge_tier": null, + "charity_donation": null + } + } +} diff --git a/lib/twitch-eventsub-ws/tests/resources/messages/channel.chat.notification-pay-it-forward.json b/lib/twitch-eventsub-ws/tests/resources/messages/channel.chat.notification-pay-it-forward.json new file mode 100644 index 00000000..a7d3b2eb --- /dev/null +++ b/lib/twitch-eventsub-ws/tests/resources/messages/channel.chat.notification-pay-it-forward.json @@ -0,0 +1,62 @@ +{ + "metadata": { + "message_id": "2246f78c-ce7b-4639-836b-d3bddc3f65ef", + "message_type": "notification", + "message_timestamp": "2024-05-14T12:31:47.995298776Z", + "subscription_type": "channel.chat.notification", + "subscription_version": "1" + }, + "payload": { + "subscription": { + "id": "96f9a91e-f1e0-43af-82ac-a6e934778805", + "status": "enabled", + "type": "channel.chat.notification", + "version": "1", + "condition": { + "broadcaster_user_id": "165080419", + "user_id": "27620241" + }, + "transport": { + "method": "websocket", + "session_id": "AgoQUlB8aB2SSsavWVfcs5ljnBIGY2VsbC1j" + }, + "created_at": "2023-11-20T16:41:22.999246448Z", + "cost": 0 + }, + "event": { + "broadcaster_user_id": "165080419", + "broadcaster_user_login": "elraenn", + "broadcaster_user_name": "Elraenn", + "chatter_user_id": "425829220", + "chatter_user_login": "kecogluali5", + "chatter_user_name": "Kecogluali5", + "chatter_is_anonymous": false, + "color": "#0000FF", + "badges": [{ "set_id": "subscriber", "id": "12", "info": "12" }], + "system_message": "Kecogluali5 is paying forward the Gift they got from CasinoZEBERUS to the community!", + "message_id": "573a20ff-8f88-499e-be2b-c7079eb76f6c", + "message": { "text": "", "fragments": [] }, + "notice_type": "pay_it_forward", + "sub": null, + "resub": null, + "sub_gift": null, + "community_sub_gift": null, + "gift_paid_upgrade": null, + "prime_paid_upgrade": null, + "pay_it_forward": { + "recipient_user_id": null, + "recipient_user_name": null, + "recipient_user_login": null, + "gifter_is_anonymous": false, + "gifter_user_id": "967793245", + "gifter_user_name": "CasinoZEBERUS", + "gifter_user_login": "casinozeberus" + }, + "raid": null, + "unraid": null, + "announcement": null, + "bits_badge_tier": null, + "charity_donation": null + } + } +} diff --git a/lib/twitch-eventsub-ws/tests/resources/messages/channel.chat.notification-resub-2.json b/lib/twitch-eventsub-ws/tests/resources/messages/channel.chat.notification-resub-2.json new file mode 100644 index 00000000..a4254480 --- /dev/null +++ b/lib/twitch-eventsub-ws/tests/resources/messages/channel.chat.notification-resub-2.json @@ -0,0 +1,75 @@ +{ + "metadata": { + "message_id": "ae24c14e-2e34-4d78-99b0-9c5586a47cd9", + "message_type": "notification", + "message_timestamp": "2024-05-14T12:31:47.995298776Z", + "subscription_type": "channel.chat.notification", + "subscription_version": "1" + }, + "payload": { + "subscription": { + "id": "dc1a3cfc-a930-4972-bf9e-0ffc4e7a8996", + "status": "enabled", + "type": "channel.chat.notification", + "version": "1", + "condition": { "broadcaster_user_id": "1971641", "user_id": "2914196" }, + "transport": { + "method": "websocket", + "session_id": "AgoQOtgGkFvXRlSkij343CndhIGY2VsbC1h" + }, + "created_at": "2023-10-06T18:04:38.807682738Z", + "cost": 0 + }, + "event": { + "broadcaster_user_id": "1971641", + "broadcaster_user_login": "streamer", + "broadcaster_user_name": "streamer", + "chatter_user_id": "49912639", + "chatter_user_login": "viewer23", + "chatter_user_name": "viewer23", + "chatter_is_anonymous": false, + "color": "", + "badges": [], + "system_message": "viewer23 subscribed at Tier 1. They've subscribed for 10 months!", + "message_id": "d62235c8-47ff-a4f4--84e8-5a29a65a9c03", + "message": { "text": "", "fragments": [] }, + "notice_type": "resub", + "sub": null, + "resub": { + "cumulative_months": 10, + "duration_months": 0, + "streak_months": null, + "sub_tier": "1000", + "is_gift": false, + "gifter_is_anonymous": null, + "gifter_user_id": null, + "gifter_user_name": null, + "gifter_user_login": null + }, + "sub_gift": null, + "community_sub_gift": null, + "gift_paid_upgrade": null, + "prime_paid_upgrade": null, + "pay_it_forward": null, + "raid": null, + "unraid": null, + "announcement": null, + "bits_badge_tier": null, + "charity_donation": null, + "shared_chat_sub": null, + "shared_chat_resub": null, + "shared_chat_sub_gift": null, + "shared_chat_community_sub_gift": null, + "shared_chat_gift_paid_upgrade": null, + "shared_chat_prime_paid_upgrade": null, + "shared_chat_pay_it_forward": null, + "shared_chat_raid": null, + "shared_chat_announcement": null, + "source_broadcaster_user_id": null, + "source_broadcaster_user_login": null, + "source_broadcaster_user_name": null, + "source_message_id": null, + "source_badges": null + } + } +} diff --git a/lib/twitch-eventsub-ws/tests/resources/messages/channel.chat.notification-resub-msg.json b/lib/twitch-eventsub-ws/tests/resources/messages/channel.chat.notification-resub-msg.json new file mode 100644 index 00000000..4f468e40 --- /dev/null +++ b/lib/twitch-eventsub-ws/tests/resources/messages/channel.chat.notification-resub-msg.json @@ -0,0 +1,77 @@ +{ + "metadata": { + "message_id": "8466103d-5c96-4a92-b6ae-8a1a5ab9d22b", + "message_type": "notification", + "message_timestamp": "2024-05-14T12:31:47.995298776Z", + "subscription_type": "channel.chat.notification", + "subscription_version": "1" + }, + "payload": { + "subscription": { + "id": "2237f256-1b83-4ec9-956e-c3578925e8e6", + "status": "enabled", + "type": "channel.chat.notification", + "version": "1", + "condition": { "broadcaster_user_id": "67931625", "user_id": "27620241" }, + "transport": { + "method": "websocket", + "session_id": "AgoQuf4yiyFuTd64mlIG4zbSOxIGY2VsbC1j" + }, + "created_at": "2023-11-19T22:08:49.127052362Z", + "cost": 0 + }, + "event": { + "broadcaster_user_id": "67931625", + "broadcaster_user_login": "amar", + "broadcaster_user_name": "Amar", + "chatter_user_id": "101572475", + "chatter_user_login": "justinfan", + "chatter_user_name": "justinfan", + "chatter_is_anonymous": false, + "color": "#FA6E02", + "badges": [ + { "set_id": "moderator", "id": "1", "info": "" }, + { "set_id": "subscriber", "id": "48", "info": "58" }, + { "set_id": "partner", "id": "1", "info": "" } + ], + "system_message": "justinfan subscribed at Tier 1. They've subscribed for 58 months!", + "message_id": "aaa15585-0f43-4c32-8c48-56d58e9567a7", + "message": { + "text": "GIB MIR DEN POKAL", + "fragments": [ + { + "type": "text", + "text": "GIB MIR DEN POKAL", + "cheermote": null, + "emote": null, + "mention": null + } + ] + }, + "notice_type": "resub", + "sub": null, + "resub": { + "cumulative_months": 58, + "duration_months": 0, + "streak_months": null, + "sub_tier": "1000", + "is_prime": false, + "is_gift": false, + "gifter_is_anonymous": null, + "gifter_user_id": null, + "gifter_user_name": null, + "gifter_user_login": null + }, + "sub_gift": null, + "community_sub_gift": null, + "gift_paid_upgrade": null, + "prime_paid_upgrade": null, + "pay_it_forward": null, + "raid": null, + "unraid": null, + "announcement": null, + "bits_badge_tier": null, + "charity_donation": null + } + } +} diff --git a/lib/twitch-eventsub-ws/tests/resources/messages/channel.chat.notification-resub.json b/lib/twitch-eventsub-ws/tests/resources/messages/channel.chat.notification-resub.json new file mode 100644 index 00000000..c4ceb8ba --- /dev/null +++ b/lib/twitch-eventsub-ws/tests/resources/messages/channel.chat.notification-resub.json @@ -0,0 +1,65 @@ +{ + "metadata": { + "message_id": "333c1c6a-475f-4c7a-bb16-fe0ae443ac32", + "message_type": "notification", + "message_timestamp": "2024-05-14T12:31:47.995298776Z", + "subscription_type": "channel.chat.notification", + "subscription_version": "1" + }, + "payload": { + "subscription": { + "id": "96f9a91e-f1e0-43af-82ac-a6e934771337", + "status": "enabled", + "type": "channel.chat.notification", + "version": "1", + "condition": { + "broadcaster_user_id": "165081337", + "user_id": "27620241" + }, + "transport": { + "method": "websocket", + "session_id": "AgoQUlB8aB2SSsavWVfcs5ljnBIGY2Vs1337" + }, + "created_at": "2023-11-20T16:41:22.999246448Z", + "cost": 0 + }, + "event": { + "broadcaster_user_id": "1337", + "broadcaster_user_login": "Cool_User", + "broadcaster_user_name": "cool_user", + "chatter_user_id": "5678", + "chatter_user_login": "someone1", + "chatter_user_name": "someone1", + "chatter_is_anonymous": false, + "color": "", + "badges": [{ "set_id": "subscriber", "id": "2", "info": "2" }], + "system_message": "someone1 subscribed at Tier 1. They've subscribed for 2 months!", + "message_id": "101ab672-fcde-4d71-8011-ac2859786cea", + "message": { "text": "", "fragments": [] }, + "notice_type": "resub", + "sub": null, + "resub": { + "cumulative_months": 2, + "duration_months": 0, + "streak_months": null, + "sub_tier": "1000", + "is_prime": false, + "is_gift": true, + "gifter_is_anonymous": false, + "gifter_user_id": "1234", + "gifter_user_name": "justinfan1", + "gifter_user_login": "justinfan1" + }, + "sub_gift": null, + "community_sub_gift": null, + "gift_paid_upgrade": null, + "prime_paid_upgrade": null, + "pay_it_forward": null, + "raid": null, + "unraid": null, + "announcement": null, + "bits_badge_tier": null, + "charity_donation": null + } + } +} diff --git a/lib/twitch-eventsub-ws/tests/resources/messages/channel.chat.notification-shared-chat-resub.json b/lib/twitch-eventsub-ws/tests/resources/messages/channel.chat.notification-shared-chat-resub.json new file mode 100644 index 00000000..01f119ab --- /dev/null +++ b/lib/twitch-eventsub-ws/tests/resources/messages/channel.chat.notification-shared-chat-resub.json @@ -0,0 +1,78 @@ +{ + "metadata": { + "message_id": "be5c6e89-13b4-48cf-ab04-f83ca62b0b57", + "message_type": "notification", + "message_timestamp": "2024-05-14T12:31:47.995298776Z", + "subscription_type": "channel.chat.notification", + "subscription_version": "1" + }, + "payload": { + "subscription": { + "id": "dc1a3cfc-a930-4972-bf9e-0ffc4e7a8996", + "status": "enabled", + "type": "channel.chat.notification", + "version": "1", + "condition": { "broadcaster_user_id": "1971641", "user_id": "2914196" }, + "transport": { + "method": "websocket", + "session_id": "AgoQOtgGkFvXRlSkij343CndhIGY2VsbC1h" + }, + "created_at": "2023-10-06T18:04:38.807682738Z", + "cost": 0 + }, + "event": { + "broadcaster_user_id": "1971641", + "broadcaster_user_login": "streamer", + "broadcaster_user_name": "streamer", + "chatter_user_id": "49912639", + "chatter_user_login": "viewer23", + "chatter_user_name": "viewer23", + "chatter_is_anonymous": false, + "color": "", + "badges": [], + "system_message": "viewer23 subscribed at Tier 1. They've subscribed for 10 months!", + "message_id": "d62235c8-47ff-a4f4--84e8-5a29a65a9c03", + "message": { "text": "", "fragments": [] }, + "notice_type": "shared_chat_resub", + "sub": null, + "resub": null, + "sub_gift": null, + "community_sub_gift": null, + "gift_paid_upgrade": null, + "prime_paid_upgrade": null, + "pay_it_forward": null, + "raid": null, + "unraid": null, + "announcement": null, + "bits_badge_tier": null, + "charity_donation": null, + "shared_chat_sub": null, + "shared_chat_resub": { + "cumulative_months": 10, + "duration_months": 0, + "streak_months": null, + "sub_tier": "1000", + "is_gift": false, + "gifter_is_anonymous": null, + "gifter_user_id": null, + "gifter_user_name": null, + "gifter_user_login": null + }, + "shared_chat_sub_gift": null, + "shared_chat_community_sub_gift": null, + "shared_chat_gift_paid_upgrade": null, + "shared_chat_prime_paid_upgrade": null, + "shared_chat_pay_it_forward": null, + "shared_chat_raid": null, + "shared_chat_unraid": null, + "shared_chat_announcement": null, + "shared_chat_bits_badge_tier": null, + "shared_chat_charity_donation": null, + "source_broadcaster_user_id": "112233", + "source_broadcaster_user_login": "streamer33", + "source_broadcaster_user_name": "streamer33", + "source_message_id": "2be7193d-0366-4453-b6ec-b288ce9f2c39", + "source_badges": [{ "set_id": "subscriber", "id": "3", "info": "3" }] + } + } +} diff --git a/lib/twitch-eventsub-ws/tests/resources/messages/channel.moderate-emoteonly.json b/lib/twitch-eventsub-ws/tests/resources/messages/channel.moderate-emoteonly.json new file mode 100644 index 00000000..4e74ffda --- /dev/null +++ b/lib/twitch-eventsub-ws/tests/resources/messages/channel.moderate-emoteonly.json @@ -0,0 +1,57 @@ +{ + "metadata": { + "message_id": "c5c679a1-f99d-4863-9f57-c434b10dc39d", + "message_type": "notification", + "message_timestamp": "2024-05-14T12:31:47.995298776Z", + "subscription_type": "channel.moderate", + "subscription_version": "2" + }, + "payload": { + "subscription": { + "id": "7297f7eb-3bf5-461f-8ae6-7cd7781ebce3", + "status": "enabled", + "type": "channel.moderate", + "version": "2", + "cost": 0, + "condition": { + "broadcaster_user_id": "423374343", + "moderator_user_id": "423374343" + }, + "transport": { + "method": "websocket", + "session_id": "AgoQUlB8aB2SSsavWVfcs5ljnBIGY2VsbC1j" + }, + "created_at": "2024-02-23T21:12:33.771005262Z" + }, + "event": { + "broadcaster_user_id": "423374343", + "broadcaster_user_login": "glowillig", + "broadcaster_user_name": "glowillig", + "moderator_user_id": "424596340", + "moderator_user_login": "quotrok", + "moderator_user_name": "quotrok", + "action": "emoteonly", + "followers": null, + "slow": null, + "vip": null, + "unvip": null, + "mod": null, + "unmod": null, + "ban": null, + "unban": null, + "warn": null, + "timeout": null, + "untimeout": null, + "raid": null, + "unraid": null, + "delete": null, + "automod_terms": null, + "unban_request": null, + "shared_chat_ban": null, + "shared_chat_unban": null, + "shared_chat_timeout": null, + "shared_chat_untimeout": null, + "shared_chat_delete": null + } + } +} diff --git a/lib/twitch-eventsub-ws/tests/resources/messages/channel.moderate-followers.json b/lib/twitch-eventsub-ws/tests/resources/messages/channel.moderate-followers.json new file mode 100644 index 00000000..f0dd40cc --- /dev/null +++ b/lib/twitch-eventsub-ws/tests/resources/messages/channel.moderate-followers.json @@ -0,0 +1,60 @@ +{ + "metadata": { + "message_id": "0a0741bb-eb9f-4337-9581-d088c2acc3b2", + "message_type": "notification", + "message_timestamp": "2024-05-14T12:31:47.995298776Z", + "subscription_type": "channel.moderate", + "subscription_version": "2" + }, + "payload": { + "subscription": { + "id": "86d99e53-2837-40cf-bc6e-c6e00698919c", + "status": "enabled", + "type": "channel.moderate", + "version": "2", + "condition": { + "broadcaster_user_id": "11148817", + "moderator_user_id": "117166826" + }, + "transport": { + "method": "websocket", + "session_id": "AgoQZgfnyKxXQ32hpzCWF4aCGBIGY2VsbC1j" + }, + "created_at": "2025-02-01T12:02:16.005321321Z", + "cost": 0 + }, + "event": { + "broadcaster_user_id": "11148817", + "broadcaster_user_login": "pajlada", + "broadcaster_user_name": "pajlada", + "source_broadcaster_user_id": null, + "source_broadcaster_user_login": null, + "source_broadcaster_user_name": null, + "moderator_user_id": "11148817", + "moderator_user_login": "pajlada", + "moderator_user_name": "pajlada", + "action": "followers", + "followers": { "follow_duration_minutes": 10080 }, + "slow": null, + "vip": null, + "unvip": null, + "mod": null, + "unmod": null, + "ban": null, + "unban": null, + "timeout": null, + "untimeout": null, + "raid": null, + "unraid": null, + "delete": null, + "automod_terms": null, + "unban_request": null, + "warn": null, + "shared_chat_ban": null, + "shared_chat_unban": null, + "shared_chat_timeout": null, + "shared_chat_untimeout": null, + "shared_chat_delete": null + } + } +} diff --git a/lib/twitch-eventsub-ws/tests/resources/messages/channel.moderate-followersoff.json b/lib/twitch-eventsub-ws/tests/resources/messages/channel.moderate-followersoff.json new file mode 100644 index 00000000..b55c096c --- /dev/null +++ b/lib/twitch-eventsub-ws/tests/resources/messages/channel.moderate-followersoff.json @@ -0,0 +1,60 @@ +{ + "metadata": { + "message_id": "b3426fa4-f7b0-4d20-827f-f620d9b9bce0", + "message_type": "notification", + "message_timestamp": "2024-05-14T12:31:47.995298776Z", + "subscription_type": "channel.moderate", + "subscription_version": "2" + }, + "payload": { + "subscription": { + "id": "86d99e53-2837-40cf-bc6e-c6e00698919c", + "status": "enabled", + "type": "channel.moderate", + "version": "2", + "condition": { + "broadcaster_user_id": "11148817", + "moderator_user_id": "117166826" + }, + "transport": { + "method": "websocket", + "session_id": "AgoQZgfnyKxXQ32hpzCWF4aCGBIGY2VsbC1j" + }, + "created_at": "2025-02-01T12:02:16.005321321Z", + "cost": 0 + }, + "event": { + "broadcaster_user_id": "11148817", + "broadcaster_user_login": "pajlada", + "broadcaster_user_name": "pajlada", + "source_broadcaster_user_id": null, + "source_broadcaster_user_login": null, + "source_broadcaster_user_name": null, + "moderator_user_id": "11148817", + "moderator_user_login": "pajlada", + "moderator_user_name": "pajlada", + "action": "followersoff", + "followers": null, + "slow": null, + "vip": null, + "unvip": null, + "mod": null, + "unmod": null, + "ban": null, + "unban": null, + "timeout": null, + "untimeout": null, + "raid": null, + "unraid": null, + "delete": null, + "automod_terms": null, + "unban_request": null, + "warn": null, + "shared_chat_ban": null, + "shared_chat_unban": null, + "shared_chat_timeout": null, + "shared_chat_untimeout": null, + "shared_chat_delete": null + } + } +} diff --git a/lib/twitch-eventsub-ws/tests/resources/messages/channel.moderate-mod.json b/lib/twitch-eventsub-ws/tests/resources/messages/channel.moderate-mod.json new file mode 100644 index 00000000..1cd30126 --- /dev/null +++ b/lib/twitch-eventsub-ws/tests/resources/messages/channel.moderate-mod.json @@ -0,0 +1,61 @@ +{ + "metadata": { + "message_id": "cf0534f2-a006-4c83-a958-346333bb631f", + "message_type": "notification", + "message_timestamp": "2024-05-14T12:31:47.995298776Z", + "subscription_type": "channel.moderate", + "subscription_version": "2" + }, + "payload": { + "subscription": { + "id": "7297f7eb-3bf5-461f-8ae6-7cd7781ebce3", + "status": "enabled", + "type": "channel.moderate", + "version": "2", + "cost": 0, + "condition": { + "broadcaster_user_id": "423374343", + "moderator_user_id": "423374343" + }, + "transport": { + "method": "websocket", + "session_id": "AgoQUlB8aB2SSsavWVfcs5ljnBIGY2VsbC1j" + }, + "created_at": "2024-02-23T21:12:33.771005262Z" + }, + "event": { + "broadcaster_user_id": "423374343", + "broadcaster_user_login": "glowillig", + "broadcaster_user_name": "glowillig", + "moderator_user_id": "424596340", + "moderator_user_login": "quotrok", + "moderator_user_name": "quotrok", + "action": "mod", + "followers": null, + "slow": null, + "vip": null, + "unvip": null, + "warn": null, + "mod": { + "user_id": "141981764", + "user_login": "twitchdev", + "user_name": "TwitchDev" + }, + "unmod": null, + "ban": null, + "unban": null, + "timeout": null, + "untimeout": null, + "raid": null, + "unraid": null, + "delete": null, + "automod_terms": null, + "unban_request": null, + "shared_chat_ban": null, + "shared_chat_unban": null, + "shared_chat_timeout": null, + "shared_chat_untimeout": null, + "shared_chat_delete": null + } + } +} diff --git a/lib/twitch-eventsub-ws/tests/resources/messages/channel.moderate-timeout.json b/lib/twitch-eventsub-ws/tests/resources/messages/channel.moderate-timeout.json new file mode 100644 index 00000000..84e4d5cc --- /dev/null +++ b/lib/twitch-eventsub-ws/tests/resources/messages/channel.moderate-timeout.json @@ -0,0 +1,66 @@ +{ + "metadata": { + "message_id": "2ea469a5-4bc8-4f95-ae08-c10b679cf038", + "message_type": "notification", + "message_timestamp": "2024-05-14T12:31:47.995298776Z", + "subscription_type": "channel.moderate", + "subscription_version": "2" + }, + "payload": { + "subscription": { + "id": "5a893cd8-c10e-4198-a620-e9f35fd6ccd6", + "status": "enabled", + "type": "channel.moderate", + "version": "2", + "condition": { + "broadcaster_user_id": "129546453", + "moderator_user_id": "129546453" + }, + "transport": { + "method": "websocket", + "session_id": "AgoQMmDnfVEhRI6iLiBniEWHkxIGY2VsbC1j" + }, + "created_at": "2024-11-27T20:01:50.171283653Z", + "cost": 0 + }, + "event": { + "broadcaster_user_id": "129546453", + "broadcaster_user_login": "nerixyz", + "broadcaster_user_name": "nerixyz", + "source_broadcaster_user_id": null, + "source_broadcaster_user_login": null, + "source_broadcaster_user_name": null, + "moderator_user_id": "129546453", + "moderator_user_login": "nerixyz", + "moderator_user_name": "nerixyz", + "action": "timeout", + "followers": null, + "slow": null, + "vip": null, + "unvip": null, + "mod": null, + "unmod": null, + "ban": null, + "unban": null, + "timeout": { + "user_id": "141981764", + "user_login": "twitchdev", + "user_name": "TwitchDev", + "reason": "test Kappa", + "expires_at": "2024-11-27T20:01:55.358149527Z" + }, + "untimeout": null, + "raid": null, + "unraid": null, + "delete": null, + "automod_terms": null, + "unban_request": null, + "warn": null, + "shared_chat_ban": null, + "shared_chat_unban": null, + "shared_chat_timeout": null, + "shared_chat_untimeout": null, + "shared_chat_delete": null + } + } +} diff --git a/lib/twitch-eventsub-ws/tests/resources/messages/channel.moderate-warn.json b/lib/twitch-eventsub-ws/tests/resources/messages/channel.moderate-warn.json new file mode 100644 index 00000000..68adc992 --- /dev/null +++ b/lib/twitch-eventsub-ws/tests/resources/messages/channel.moderate-warn.json @@ -0,0 +1,65 @@ +{ + "metadata": { + "message_id": "e8edc592-5550-4aa5-bba6-39e31a2be435", + "message_type": "notification", + "message_timestamp": "2024-05-14T12:31:47.995298776Z", + "subscription_type": "channel.moderate", + "subscription_version": "2" + }, + "payload": { + "subscription": { + "id": "7297f7eb-3bf5-461f-8ae6-7cd7781ebce3", + "status": "enabled", + "type": "channel.moderate", + "version": "2", + "cost": 0, + "condition": { + "broadcaster_user_id": "423374343", + "moderator_user_id": "424596340" + }, + "transport": { + "method": "websocket", + "session_id": "AgoQUlB8aB2SSsavWVfcs5ljnBIGY2VsbC1j" + }, + "created_at": "2024-02-23T21:12:33.771005262Z" + }, + "event": { + "broadcaster_user_id": "423374343", + "broadcaster_user_login": "glowillig", + "broadcaster_user_name": "glowillig", + "source_broadcaster_user_id": "41292030", + "source_broadcaster_user_login": "adflynn404", + "source_broadcaster_user_name": "adflynn404", + "moderator_user_id": "424596340", + "moderator_user_login": "quotrok", + "moderator_user_name": "quotrok", + "action": "warn", + "followers": null, + "slow": null, + "vip": null, + "unvip": null, + "warn": { + "user_id": "141981764", + "user_login": "twitchdev", + "user_name": "TwitchDev", + "reason": "cut it out", + "chat_rules_cited": null + }, + "unmod": null, + "ban": null, + "unban": null, + "timeout": null, + "untimeout": null, + "raid": null, + "unraid": null, + "delete": null, + "automod_terms": null, + "unban_request": null, + "shared_chat_ban": null, + "shared_chat_unban": null, + "shared_chat_timeout": null, + "shared_chat_untimeout": null, + "shared_chat_delete": null + } + } +} diff --git a/lib/twitch-eventsub-ws/tests/resources/messages/channel.moderate.json b/lib/twitch-eventsub-ws/tests/resources/messages/channel.moderate.json new file mode 100644 index 00000000..2a9e9525 --- /dev/null +++ b/lib/twitch-eventsub-ws/tests/resources/messages/channel.moderate.json @@ -0,0 +1,60 @@ +{ + "metadata": { + "message_id": "bf6e248f-a523-4bf8-b215-ea1822e60223", + "message_type": "notification", + "message_timestamp": "2024-05-14T12:31:47.995298776Z", + "subscription_type": "channel.moderate", + "subscription_version": "2" + }, + "payload": { + "subscription": { + "id": "86d99e53-2837-40cf-bc6e-c6e00698919c", + "status": "enabled", + "type": "channel.moderate", + "version": "2", + "condition": { + "broadcaster_user_id": "11148817", + "moderator_user_id": "117166826" + }, + "transport": { + "method": "websocket", + "session_id": "AgoQZgfnyKxXQ32hpzCWF4aCGBIGY2VsbC1j" + }, + "created_at": "2025-02-01T12:02:16.005321321Z", + "cost": 0 + }, + "event": { + "broadcaster_user_id": "11148817", + "broadcaster_user_login": "pajlada", + "broadcaster_user_name": "pajlada", + "source_broadcaster_user_id": null, + "source_broadcaster_user_login": null, + "source_broadcaster_user_name": null, + "moderator_user_id": "11148817", + "moderator_user_login": "pajlada", + "moderator_user_name": "pajlada", + "action": "followers", + "followers": { "follow_duration_minutes": 0 }, + "slow": null, + "vip": null, + "unvip": null, + "mod": null, + "unmod": null, + "ban": null, + "unban": null, + "timeout": null, + "untimeout": null, + "raid": null, + "unraid": null, + "delete": null, + "automod_terms": null, + "unban_request": null, + "warn": null, + "shared_chat_ban": null, + "shared_chat_unban": null, + "shared_chat_timeout": null, + "shared_chat_untimeout": null, + "shared_chat_delete": null + } + } +} diff --git a/lib/twitch-eventsub-ws/tests/resources/messages/channel.update.json b/lib/twitch-eventsub-ws/tests/resources/messages/channel.update.json new file mode 100644 index 00000000..79e7eb35 --- /dev/null +++ b/lib/twitch-eventsub-ws/tests/resources/messages/channel.update.json @@ -0,0 +1,34 @@ +{ + "metadata": { + "message_id": "beb72a37-0c04-4d7e-9934-f611ddc0e869", + "message_type": "notification", + "message_timestamp": "2024-05-14T12:31:47.995298776Z", + "subscription_type": "channel.update", + "subscription_version": "1" + }, + "payload": { + "subscription": { + "id": "f1c2a387-161a-49f9-a165-0f21d7a4e1c4", + "type": "channel.update", + "version": "1", + "status": "enabled", + "cost": 0, + "condition": { "broadcaster_user_id": "1337" }, + "transport": { + "method": "websocket", + "session_id": "AgoQUlB8aB2SSsavWVfcs5ljnBIGY2VsbC1j" + }, + "created_at": "2019-11-16T10:11:12.123Z" + }, + "event": { + "broadcaster_user_id": "1337", + "broadcaster_user_login": "cool_user", + "broadcaster_user_name": "Cool_User", + "title": "Best Stream Ever", + "language": "en", + "category_id": "21779", + "category_name": "Fortnite", + "is_mature": false + } + } +} diff --git a/lib/twitch-eventsub-ws/tests/resources/messages/session-welcome.json b/lib/twitch-eventsub-ws/tests/resources/messages/session-welcome.json new file mode 100644 index 00000000..8437623e --- /dev/null +++ b/lib/twitch-eventsub-ws/tests/resources/messages/session-welcome.json @@ -0,0 +1,16 @@ +{ + "metadata": { + "message_id": "faf21c17-82d3-4479-8daa-295f16b706f0", + "message_type": "session_welcome", + "message_timestamp": "2023-07-19T14:56:51.634234626Z" + }, + "payload": { + "session": { + "id": "AQoQILE98gtqShGmLD7AM6yJThAB", + "status": "connected", + "connected_at": "2023-07-19T14:56:51.616329898Z", + "keepalive_timeout_seconds": 10, + "reconnect_url": null + } + } +} diff --git a/lib/twitch-eventsub-ws/tests/resources/messages/stream.offline.json b/lib/twitch-eventsub-ws/tests/resources/messages/stream.offline.json new file mode 100644 index 00000000..c5f8dd23 --- /dev/null +++ b/lib/twitch-eventsub-ws/tests/resources/messages/stream.offline.json @@ -0,0 +1,29 @@ +{ + "metadata": { + "message_id": "ee312d92-d9bb-4d4f-9e94-3a5e051940f3", + "message_type": "notification", + "message_timestamp": "2024-05-14T12:31:47.995298776Z", + "subscription_type": "stream.offline", + "subscription_version": "1" + }, + "payload": { + "subscription": { + "id": "f1c2a387-161a-49f9-a165-0f21d7a4e1c4", + "type": "stream.offline", + "version": "1", + "status": "enabled", + "cost": 0, + "condition": { "broadcaster_user_id": "1337" }, + "created_at": "2019-11-16T10:11:12.123Z", + "transport": { + "method": "websocket", + "session_id": "AgoQUlB8aB2SSsavWVfcs5ljnBIGY2VsbC1j" + } + }, + "event": { + "broadcaster_user_id": "1337", + "broadcaster_user_login": "cool_user", + "broadcaster_user_name": "Cool_User" + } + } +} diff --git a/lib/twitch-eventsub-ws/tests/resources/messages/stream.online.json b/lib/twitch-eventsub-ws/tests/resources/messages/stream.online.json new file mode 100644 index 00000000..e28c8576 --- /dev/null +++ b/lib/twitch-eventsub-ws/tests/resources/messages/stream.online.json @@ -0,0 +1,32 @@ +{ + "metadata": { + "message_id": "ecaf20f2-6b08-4a17-ba14-581130d93c95", + "message_type": "notification", + "message_timestamp": "2024-05-14T12:31:47.995298776Z", + "subscription_type": "stream.online", + "subscription_version": "1" + }, + "payload": { + "subscription": { + "id": "f1c2a387-161a-49f9-a165-0f21d7a4e1c4", + "type": "stream.online", + "version": "1", + "status": "enabled", + "cost": 0, + "condition": { "broadcaster_user_id": "1337" }, + "transport": { + "method": "websocket", + "session_id": "AgoQUlB8aB2SSsavWVfcs5ljnBIGY2VsbC1j" + }, + "created_at": "2019-11-16T10:11:12.123Z" + }, + "event": { + "id": "9001", + "broadcaster_user_id": "1337", + "broadcaster_user_login": "cool_user", + "broadcaster_user_name": "Cool_User", + "type": "live", + "started_at": "2020-10-11T10:11:12.123Z" + } + } +} diff --git a/lib/twitch-eventsub-ws/tests/src/parse.cpp b/lib/twitch-eventsub-ws/tests/src/parse.cpp new file mode 100644 index 00000000..9069dcee --- /dev/null +++ b/lib/twitch-eventsub-ws/tests/src/parse.cpp @@ -0,0 +1,124 @@ +#include "twitch-eventsub-ws/listener.hpp" +#include "twitch-eventsub-ws/session.hpp" + +#include +#include + +#include +#include +#include + +namespace { + +using namespace chatterino::eventsub::lib; + +std::filesystem::path baseDir() +{ + std::filesystem::path snapshotDir(__FILE__); + return snapshotDir.parent_path().parent_path() / "resources" / "messages"; +} + +std::filesystem::path filePath(std::string_view name) +{ + return baseDir() / name; +} + +std::vector discover() +{ + std::vector files; + for (const auto &entry : std::filesystem::directory_iterator{baseDir()}) + { + if (entry.is_regular_file()) + { + auto name = entry.path().filename().string(); + if (name.ends_with(".json")) + { + files.emplace_back(name.substr(0, name.length() - 5)); + } + } + } + return files; +} + +boost::beast::flat_buffer readToFlatBuffer(const std::filesystem::path &path) +{ + std::ifstream istream(path); + std::ostringstream buffer; + buffer << istream.rdbuf(); + + boost::beast::flat_buffer buf; + auto inner = buf.prepare(buffer.view().size()); + std::memcpy(inner.data(), buffer.view().data(), inner.size()); + buf.commit(inner.size()); + return buf; +} + +class NoOpListener : public chatterino::eventsub::lib::Listener +{ + void onSessionWelcome(messages::Metadata metadata, + payload::session_welcome::Payload payload) override + { + } + + void onNotification(messages::Metadata metadata, + const boost::json::value &jv) override + { + } + + void onChannelBan(messages::Metadata metadata, + payload::channel_ban::v1::Payload payload) override + { + } + + void onStreamOnline(messages::Metadata metadata, + payload::stream_online::v1::Payload payload) override + { + } + + void onStreamOffline(messages::Metadata metadata, + payload::stream_offline::v1::Payload payload) override + { + } + + void onChannelChatNotification( + messages::Metadata metadata, + payload::channel_chat_notification::v1::Payload payload) override + { + } + + void onChannelUpdate(messages::Metadata metadata, + payload::channel_update::v1::Payload payload) override + { + } + + void onChannelChatMessage( + messages::Metadata metadata, + payload::channel_chat_message::v1::Payload payload) override + { + } + + void onChannelModerate( + messages::Metadata metadata, + payload::channel_moderate::v2::Payload payload) override + { + } +}; + +} // namespace + +class TestHandleMessageP : public ::testing::TestWithParam +{ +}; + +TEST_P(TestHandleMessageP, Run) +{ + auto buf = readToFlatBuffer(filePath(GetParam() + ".json")); + + std::unique_ptr listener = std::make_unique(); + auto ec = handleMessage(listener, buf); + ASSERT_FALSE(ec.failed()) + << ec.what() << ec.message() << ec.location().to_string(); +} + +INSTANTIATE_TEST_SUITE_P(HandleMessage, TestHandleMessageP, + testing::ValuesIn(discover()));