jammsen / docker-palworld-dedicated-server

Docker container to easily provision and manage Palworld Dedicated Server
https://hub.docker.com/r/jammsen/palworld-dedicated-server
MIT License
911 stars 158 forks source link

[Feature Request] Add Discord Webhooks #120

Closed SLYROOKO closed 7 months ago

SLYROOKO commented 8 months ago

Have you read the Important information text above

Describe the feature

Discord Webhook with corresponding optional notifications for player joining{current player count same message), server start, server close.

Additional information

Final checks

ericellb commented 8 months ago

This isn't something the maintainer is going to do IMO.

If you'd like to do it I'll provide a solution.

  1. Setup a Web Server (Use express or something along those lines)
  2. Make it use commands over an RCON client on an interval (You can use https://github.com/radj307/ARRCON, or some language specific library)
  3. Setup a discord webhook to publish this data
  4. Profit!

I personally setup a similar solution to monitor my server on HomeAssisant

jammsen commented 8 months ago

Hey @SLYROOKO Could you please add an example scenario on how you would like this to work?

Because im pretty sure i can do online interval updates and send that to somewhere. Afaik the "player-joined-event" and something similar is afaik NOT accessable to me or the user, as well as other events. Server-Start and Interval-tasks like Backup and Restarts and Stop would be, i think, the only option to "send something somewhere".

But please explain what you mean in more detail.

This isn't something the maintainer is going to do IMO.

Hey @ericellb - I dont want to be mean, but how about we listen first and then assume the assumable? 😄

SLYROOKO commented 8 months ago

I was going to suggest monitoring the logs to get these events, but I see there is no way to get player login events. Maybe instead for now a good alternative would be an hourly update of current players online and a list of usernames, which could be obtained from the rcon with admin command "/ShowPlayers" and parse that output.

For the Server Status events:

ericellb commented 8 months ago

@jammsen

Hey @ericellb - I dont want to be mean, but how about we listen first and then assume the assumable? 😄

I'm all for listening, I didn't mean to step on any toes.

However I believe in the Unix Philosophy, and that a tool like this is best suited as its own image/service. I want to say love your maintenance on this so far, running smooth!

jammsen commented 8 months ago

I was going to suggest monitoring the logs to get these events, but I see there is no way to get player login events.

Yeah 😢

Maybe instead for now a good alternative would be an hourly update of current players online and a list of usernames, which could be obtained from the rcon with admin command "/ShowPlayers" and parse that output.

Yeah but im not sure if i would make a parser for this

  • ENV var to set webhook URL
  • ENV var for Custom Server Start Message and Server Shutdown message etc.

Would be 1 webhookurl and 9 VARS setup 3 events (title, description, color)

Example here: image

jammsen commented 8 months ago

Thats just a test, would that be suffiecent?

SLYROOKO commented 8 months ago

Yep, perfectly suits my use case.

acelan commented 8 months ago

Actually, I just wrote a similar script to monitor the player online and offline. We can get the player online status by rcon, and regular update the data in our script, so that we can know player is online or offline when a new record appears or disappears.

BTW, I register a bot to discord to be want to do more things, so here is the code snip.

class PalworldBot(discord.Client):
    prev_online_players = []

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    async def setup_hook(self) -> None:
        # create the background task and run it in the background
        self.check_online_players.start()

    async def on_ready(self):
        print(f'Logged on as {self.user}!')
        print('------')

    async def get_online_players(self):
        timeout = 1
        command = "showplayers"
        #print("get_online_players()")
        players = []
        text = await rcon(command, host=rcon_addr, port=rcon_port, passwd=rcon_passwd, timeout=timeout)
        if text:
           print(text, flush=True)
           for line in text.splitlines():
               player = line.split(',')
               if len(player) != 3:        # not player
                   continue
               if player[0] == 'name':     # it's title
                   continue
               players.append(player)

        return players

    @tasks.loop(seconds=30)  # task runs every 30 seconds
    async def check_online_players(self):
        await self.wait_until_ready()
        online_players = await self.get_online_players()
        print(f"online_players = {online_players}")
        print(f"prev_online_players = {self.prev_online_players}")

        msg = ""
        channel = self.get_channel(discord_channel)  # channel ID goes here
        for player in online_players:
            if player not in self.prev_online_players:
                print(f"Player {player[0]} is online")
                msg = f"Player {player[0]} is online"
                await channel.send(msg)
        for player in self.prev_online_players:
            if player not in online_players:
                print(f"Player {player[0]} is offline")
                msg = f"Player {player[0]} is offline"
                await channel.send(msg)

        self.prev_online_players = online_players
jammsen commented 8 months ago

Hey @SLYROOKO @acelan Would you be able for a Call in Discord to talk about this? I think the topic is up to a certain point easy to solve, BUT after that point this topic explodes with complexity.

My timezone is Germany. What would be yours?

jammsen commented 8 months ago

Hey @SLYROOKO @acelan I have added a start and stop function already pushed this to master. Please go ahead and try it out and give me feedback and please tell me if you would you be able for a Call in Discord to talk about this?

SLYROOKO commented 8 months ago

I'm U.S. East. I'll give it a test tonight and write my findings here. As for complexity of this topic, I assume it becomes a issue of use case. For me it is useful because it's a way to notify players of a server "hey your friends are playing right now" and "You can't log on? it's the server". Is there a particular use case you wanted to discuss? If so I have some time this weekend?

SLYROOKO commented 8 months ago

Working for Starting, Updating and Installing messages. Can't seem to get Server Stopped message to work.

SLYROOKO commented 8 months ago
log

Running on Synology Nas

acelan commented 8 months ago

I can see the 3 discord webhook messages shown correctly on my discord server.

jammsen commented 8 months ago

Working for Starting, Updating and Installing messages. Can't seem to get Server Stopped message to work.

You need to have the option enabled, in the same section in this script its writing the other messages you have. https://github.com/jammsen/docker-palworld-dedicated-server/blob/develop/servermanager.sh#L52

jammsen commented 8 months ago

Is there a particular use case you wanted to discuss? If so I have some time this weekend?

@acelan @SLYROOKO Yes, use-case of "online-players" I dont now both of your timezones but im fine with the weekend or with late evening for me an like afternoon for you guys?

acelan commented 8 months ago

I'm fromTaiwan +8 timezone. I'm available all day from tomorrow, and the whole week next week. So, ping me anytime when you want to chat with me.

jammsen commented 8 months ago

Would be easier if you guys are in the Discord @acelan @SLYROOKO

SLYROOKO commented 8 months ago

Working for Starting, Updating and Installing messages. Can't seem to get Server Stopped message to work.

You need to have the option enabled, in the same section in this script its writing the other messages you have. https://github.com/jammsen/docker-palworld-dedicated-server/blob/develop/servermanager.sh#L52

Joined the DIscord. And yes WEBHOOK_ENABLED = true. I'm getting the other webhook messages, just not send_webhook_notification "$WEBHOOK_STOP_TITLE" "$WEBHOOK_STOP_DESCRIPTION" "$WEBHOOK_STOP_COLOR". It may have to do with the way container's are stopped in my OS seeing that other people are not seeing this problem. I suspect that all the processes stop before getting to that line.

Can somebody else running on synology os verify this?

jammsen commented 8 months ago

Hey @SLYROOKO I have added this to the term_handler which handles the clean-save-shutdown see here but your OS might just handle things in another weird way that doesnt trigger stuff in a good and normal way.

i could just move it to after https://github.com/jammsen/docker-palworld-dedicated-server/blob/develop/servermanager.sh#L74 Line 74.

Not sure if thats a clean way for the other stops though, would need to test that.

jammsen commented 8 months ago

Hey @SLYROOKO i have added another mechanic to catch other signals, i hope, with that, the new develop image is just done baking, please go ahead and try it out for me okay?

Feedback is a must 🤣 Need to know if that works and can be released to prod/latest.

SLYROOKO commented 8 months ago

Didn't work

jammsen commented 8 months ago

Hey @SLYROOKO - I tested it on 3 systems with 3 different tools and did work everywhere. I caught everything i could catch fresh a shell POV i think. Questions:

SLYROOKO commented 8 months ago

Yes, used [https://hub.docker.com/layers/jammsen/palworld-dedicated-server/develop/images/sha256-d93a14a2e88eb5260bceed218d631ce6d8c7398d8cd0713650eced69e922b0bf?context=explore]

OS: Synology OS created a new instance of this image on "container manager" program (gui container manager) Expected Behavior: After steam update and server is running fine, i stop the container expecting the server termination message. Actual: I see all the other webhook messages get sent. except the Server termination message. Logs show "broadcasted done"

jammsen commented 7 months ago

@SLYROOKO Thats why i wanted a call with you on the weekend 😞 but nothing happend.

I think Synology doesnt respect signal codes here, because very covered 2 out of 2 cases how the system will be terminated.

jammsen commented 7 months ago

The update is now on master/latest

calvinli723 commented 7 months ago

Would it be possible to add support for webhooks in multiple discord servers?

jammsen commented 7 months ago

@calvinli723

Would it be possible to add support for webhooks in multiple discord servers?

Well at the moment the field is a "string" and thats solo for sending data.

I could rework it to be an array and then someone could add X amount of urls. The send-processing would need to be reworked, but i dont think that would a problem. But i dont have any idea if webhook urls, have sending limits per seconds/minutes/hours, that could be triggered here.

Possible yes, useful? Dont to the user to decide.

What you do had planned? @calvinli723

calvinli723 commented 7 months ago

Rework into an array would work but we don't want to break existing configs that expect the variable to be just a string right? So maybe we can add another variable? Or is there some fancy shell script logic to check whether the variable has a string or a list in it?

jammsen commented 7 months ago

@calvinli723 Well some dark voodoo shell magic is always possible like checking if there is an ( or ) in the variable. But the other way works too. Add it to the Changelog, describe it as Breaking-Change and use an @ function in Discord or so. I think its all a matter of communication and transparency. But you have a point, maybe you are the edge-cass under 150 users, who wants this as only 1 person.

jammsen commented 7 months ago

This is fixed in the release on latest from 5 minutes ago. See Changelogs or Discord message regarding the new release and what to lookout for. We dont include the playerlist part and i didnt see any motivation from the community to talk to me, while i offered it now 2 weeks.

@calvinli723 if you want multiple webhook-urls please raise a new feature request, or this issue will be open forever 😢 Sorry for the bother.

Im closing this issue as resolved, feel free to reach out again if you need help.

If you like this project, please consider giving this repo and the Docker-Hub-Repo a Star.

jammsen commented 7 months ago

Actually, I just wrote a similar script to monitor the player online and offline. We can get the player online status by rcon, and regular update the data in our script, so that we can know player is online or offline when a new record appears or disappears.

BTW, I register a bot to discord to be want to do more things, so here is the code snip.

class PalworldBot(discord.Client):
    prev_online_players = []

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    async def setup_hook(self) -> None:
        # create the background task and run it in the background
        self.check_online_players.start()

    async def on_ready(self):
        print(f'Logged on as {self.user}!')
        print('------')

    async def get_online_players(self):
        timeout = 1
        command = "showplayers"
        #print("get_online_players()")
        players = []
        text = await rcon(command, host=rcon_addr, port=rcon_port, passwd=rcon_passwd, timeout=timeout)
        if text:
           print(text, flush=True)
           for line in text.splitlines():
               player = line.split(',')
               if len(player) != 3:        # not player
                   continue
               if player[0] == 'name':     # it's title
                   continue
               players.append(player)

        return players

    @tasks.loop(seconds=30)  # task runs every 30 seconds
    async def check_online_players(self):
        await self.wait_until_ready()
        online_players = await self.get_online_players()
        print(f"online_players = {online_players}")
        print(f"prev_online_players = {self.prev_online_players}")

        msg = ""
        channel = self.get_channel(discord_channel)  # channel ID goes here
        for player in online_players:
            if player not in self.prev_online_players:
                print(f"Player {player[0]} is online")
                msg = f"Player {player[0]} is online"
                await channel.send(msg)
        for player in self.prev_online_players:
            if player not in online_players:
                print(f"Player {player[0]} is offline")
                msg = f"Player {player[0]} is offline"
                await channel.send(msg)

        self.prev_online_players = online_players

Hey @acelan - i just added a playerdetection to the image, feel free to try it out, example screenshots are in Discord in the releases channel.

navishachiku commented 4 months ago

Can I turn off only player online notifications? I just want it to be used to notify the server of the status of startup and shutdown.

jammsen commented 4 months ago

Can I turn off only player online notifications? I just want it to be used to notify the server of the status of startup and shutdown.

https://github.com/jammsen/docker-palworld-dedicated-server/blob/develop/docs/ENV_VARS.md

Read the docs ...

navishachiku commented 4 months ago

I have read it, but I was too focused on the description of the WEBHOOK_* series. After your reminder, I read it completely again and noticed that using RCON_PLAYER_DETECTION should be enough. Thank you!