Skip to content

Creating custom Events and message mapping

Jacek W edited this page Dec 19, 2023 · 4 revisions

If you manage your own event and you think it will add value to TikTokJava community I really encourge you to contribute and merge your code to library :)

Nomencrature

  • Message is packet of data send by Tiktok in protocol buffer format, for example WebcastGiftMessage
  • Event is object created by TikTokLiveJava, for example TikTokGiftEvent

Incoming Messages

First step is to understand incoming data from TikTok. It is send as bytes that are later parsed to protocol buffer classes.

Library use TikTokLiveJava/API/src/main/proto/webcast.proto file that defines Messages structure, and generate java classes

All incoming messages from TikTok have Webcast prefix, For example WebcastGiftMessage

Remeber that webcast.proto file is not always up to data with TikTok so you might not found some messages

Catching your TikTok message

Run this code and wait unitl your desire message will be display. For example If we want to know what is the message name when someone sends chat message, just

  • Run this code
  • Open TikTok in browser, sends message to chat
  • Look at the program console what message name was displayd
  • you should see Current message is WebcastChatMessage
TikTokLive.newClient("test")
          .onWebsocketResponse((liveClient, event) ->
                {
                    var messages =event.getResponse().getMessagesList();
                    for(var message: messages)
                    {
                        var name = message.getMethod();
                        System.out.printLine("Current message is "+name);
                    }
                }).buildAndConnect();

Mapping messages to event

Now we know that message name is WebcastChatMessage and we want to map it to our new event

To doing so we can use onMapping method that provides mappings utilitis In the best scenario protocol buffer class is already generated for our message so we can use mapper.webcastObjectToEvent()

  • That takes class of message as first parameter
  • Lambda function with message object as input and event object as output
      TikTokLive.newClient("test")
                .onMapping(mapper ->
                {
                      mapper.forMessage(WebcastChatMessage.class)
                            .onMapping((inputBytes, messageName, mapperHelper) ->
                            {
                                System.out.println("onMapping mapping: " + messageName);
                                var message = mapperHelper.bytesToWebcastObject(inputBytes, WebcastChatMessage.class);
                                var language = chatMessage.getContentLanguage();
                                var userName = chatMessage.getUser().getNickname();
                                var content= chatMessage.getContent();
                                var event = new CustomChatEvent(language, userName, content);
                                return MappingResult.of(message, event);
                            })
                }).buildAndConnect();

What if there is not class for my message?

What if you really want to listen for WebcastBottomMessage message but is not defined in proto file?

You can use mapper.bytesToEvent() that takes as input bytes of selected message then with ProtocolUtils.getProtocolBufferStructure(bytes); you can create structer of message and display it to console so you will see how does it looks like

              mapper.forMessage("WebcastMemberMessage")
                     .onBeforeMapping((inputBytes, messageName, mapperHelper) ->
                     {
                                if (mapperHelper.isMessageHasProtoClass(messageName)) {
                                    var messageObject = mapperHelper.bytesToWebcastObject(inputBytes, messageName);
                                    //    System.out.println(mapperHelper.toJson(messageObject));
                                } else {
                                    var structure = mapperHelper.bytesToProtoBufferStructure(inputBytes);
                                    //     System.out.println(structure.toJson());
                                }
                                return inputBytes;
                   });

Register and fire custom event

Lets create custom event, it need to extends TikTokEvent

    @Data
    public class CustomChatEvent extends TikTokEvent {
        private final String langauge;
        private final String userName;
        private final String message;

        public CustomChatEvent(String language, String userName, String message) {
            this.langauge = language;
            this.userName = userName;
            this.message = message;
        }
    }

Use .onCustomEvent in order to register your event to library and its handler

and make onMapping that will returns your event object for some tiktok message

 public static void main(String[] args) {
        TikTokLive.newClient("test")
                .onEvent(CustomChatEvent.class, (liveClient, event) ->
                {
                    System.out.println("hello world!");
                })
                .onMapping(mapper ->
                {
              mapper.forMessage("WebcastMemberMessage")
                    .onMapping((inputBytes, messageName, mapperHelper) ->
                            {
                                System.out.println("onMapping mapping: " + messageName);
                                var message = mapperHelper.bytesToWebcastObject(inputBytes, WebcastChatMessage.class);
                                var language = message.getContentLanguage();
                                var userName = message.getUser().getNickname();
                                var content = message.getContent();
                                var event = new CustomChatEvent(language, userName, content);
                                return MappingResult.of(message, event);
                            })
                }).buildAndConnect();

    }