Skip to content

Commit

Permalink
Added readme, license, and setup. Updated pipfile to reflect only nee…
Browse files Browse the repository at this point in the history
…ded packages.
  • Loading branch information
Dateranoth committed Feb 3, 2020
1 parent 4dbcd17 commit 510272b
Show file tree
Hide file tree
Showing 10 changed files with 198 additions and 39 deletions.
21 changes: 21 additions & 0 deletions RustServerAutoUpdate/LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) [year] [fullname]

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
2 changes: 0 additions & 2 deletions RustServerAutoUpdate/Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ verify_ssl = true
[packages]
requests = "*"
websockets = "*"
websocket-client = "*"
timeloop = "*"

[requires]
python_version = "3.7"
25 changes: 1 addition & 24 deletions RustServerAutoUpdate/Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

90 changes: 90 additions & 0 deletions RustServerAutoUpdate/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Auto Update an Oxide Rust Server. Can be used with any server, but designed around using LGSM.

This program was written to allow automatically updating Oxide when a new version is detected. It also allows for notification messages to be sent via Discord and RCON.

This application does not require any input to run, but it will default to creating a configuration file in the same directory it is executed from.
To change this directory, please specify on the command line. rusterverautoupdate.py /myconfig/path/ SERVER1
SERVER1 is optional, but can be used to run mutliple instances using the same configuration. Each instance should have unique settings placed in their section.
rustserverautoupdate.ini will be created on first run, and updated if any new options are added or removed.

REQUIRES: packages: requests, websockets


*oxide_log_dir
* Directory of the oxide log files.
* DEFAULT: ~/serverfiles/oxide/logs
*oxide_git_url
* URL of Oxide GIT. This is used to check for the latest release. Has not been tested against non-default repositories.
* DEFAULT: https://api.github.com/repositories/94599577/releases/latest
*oxide_check_time_in_min
* How long to wait between update checks in minutes.
* DEFAULT: 15
*oxide_auto_update
* Enable auto updates. If enabled. bash command below is ran after last notification.
* DEFAULT: no
*bash_get_update_command
* Commands to run after update detected and last notification has been sent.
* DEFAULT: ~/./rustserver stop | ~/./rustserver mods-update | ~/./rustserver start
*use_rcon
* Use RCON to send notification to server before updating.
* DEFAULT: yes
*use_discord
* Use Discord to send notification to channel before updating.
* DEFAULT: no
*rcon_ip
* RCON IP
* DEFAULT: 127.0.0.1
*rcon_port
* RCON Port
* DEFAULT: 28016
*rcon_pass
* RCON Password
* DEFAULT: CHANGE_ME
*discord_webhook
* Webhook from Discord Bot Setup.
* DEFAULT:
*discord_bot_name
* Bot Name to Display to Discord
* DEFAULT: RustPythonBot
*discord_bot_avatar_url
* Bot Avatar Image URL
* DEFAULT:
*discord_msg_game_name
* Discord Message: Game Name to Display.
* DEFAULT: My Rust Game
*discord_msg_server_name
* Discord Message: Name of Server
* DEFAULT: My Server
*discord_msg_server_ip_port
* Discord Message SERVER IP:PORT to Display.
* DEFAULT: 127.0.0.1:28015
*discord_msg_server_host_name
* Discord Message: Host Name to Display.
* DEFAULT:
*discord_msg_title
* Discord Message: Title to Display.
* DEFAULT: 🚧 ALERT
*send_15min_warn
* Send 15 Minute Warning Before Update.
* DEFAULT: yes
*send_10min_warn
* Send 10 Minute Warning Before Update.
* DEFAULT: yes
*send_5min_warn
* Send 5 Minute Warning Before Update.
* DEFAULT: yes
*send_1min_warn
* Send 1 Minute Warning Before Update.
* DEFAULT: yes
*15min_msg
* Message to be displayed for 15 minute warning.
* DEFAULT: Oxide Update Detected. Server will restart in 15 minutes for update.
*10min_msg
* Message to be displayed for 10 minute warning.
* DEFAULT: Oxide Update Scheduled. Server will restart in 10 minutes for update.
*5min_msg
* Message to be displayed for 5 minute warning.
* DEFAULT: Oxide Update Scheduled. Server will restart in 5 minutes for update.
*1min_msg
* Message to be displayed for 1 minute warning.
* DEFAULT: FINAL WARNING! SERVER RESTARTING FOR OXIDE UPDATE IN 1 MINUTE!!
47 changes: 40 additions & 7 deletions RustServerAutoUpdate/RustServerAutoUpdate.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ def __init__(self, configPath = '', configSection = 'SERVER1'):
self.msg05Min = confsec['5min_msg']
self.msg01Min = confsec['1min_msg']

#To preserve comments. Load defaults first, then load user values. Then write file. Then read file directly again without allow_no_value to have clean input to work with.
#subprocess.run for running shell commands
def setup_configuration(self, configPath, configSection):
"""Read INI file and update with new options if necessary"""
confComments = OrderedDict({'DEFAULT': {'# This is the Default configuration.': None,
Expand All @@ -52,9 +50,9 @@ def setup_configuration(self, configPath, configSection):
'oxide_git_url': 'https://api.github.com/repositories/94599577/releases/latest',
'oxide_check_time_in_min': '15',
'oxide_auto_update': 'yes',
'bash_get_update_command': '~/./rustserver stop | ~/./rustserver mods-update',
'bash_get_update_command': '~/./rustserver stop | ~/./rustserver mods-update | ~/./rustserver start',
'use_rcon': 'yes',
'use_discord': 'yes',
'use_discord': 'no',
'rcon_ip': '127.0.0.1',
'rcon_port': '28016',
'rcon_pass': 'CHANGE_ME',
Expand Down Expand Up @@ -107,6 +105,8 @@ def setup_configuration(self, configPath, configSection):
self.config.read(configFile, encoding='utf-8')

def check_variables(self, case):
"""Check variables to confirm they will not cause errors.
Fill in generic defaults if non-required variables are empty."""
if case == 1:
if not self.discordWebHook.strip():
raise RustMonitorVariableError('discord_webhook', 'Discord Bot is enabled, but no webHook was provided.')
Expand Down Expand Up @@ -140,6 +140,7 @@ def check_variables(self, case):
if not self.rconBotName.strip():
self.discordBotName = 'Unknown Bot'
def send_msgs(self, msg):
"""Containted method to send messages to both discord and RCON"""
#TODO: Add logging to exception messages.
if self.useDiscord:
try:
Expand All @@ -155,7 +156,7 @@ async def update_loop(self):
self.stop = False
while not self.stop:
response = self.oxideBot.check_update()
sleepMultiplier = 1
sleepMultiplier = 60
if response[0]:
if self.send15MinWarn:
with ThreadPoolExecutor() as executor:
Expand Down Expand Up @@ -221,8 +222,40 @@ def signal_handler(signum, frame):
print("\nStopping Rust Server Auto Update")
raise GracefulExit()

if __name__ == "__main__":
def argumenthelp():
print("\nSyntax: rustserverautoupdate.py -c <Path to Configuration INI> [-s <Section Name - Used for multiple instances>]\n"
"Example: rustserverautoupdate.py -c \home\rustserver\rustserverautoupdate -s SERVER1\n"
"\n"
"Check for updates. Return Space Separated String Array (Boolean update url, updatestring, runningversion, latestversion)\n\n"
"REQUIRED INPUT - CHOOSE ONE:\n"
"-c --configpath Path where Configuration File is Stored. MUST HAVE R.\n"
"OPTIONAL INPUT:\n"
"-s --section Section Name for configuration. This allows for multiple instances to be ran from same configuration.\n")
def main(argv):
configPath = ""
sectionName = ""
try:
opts, args = getopt.getopt(argv,"hc:s:",["help", "configpath=", "section="])
except getopt.GetoptError as err:
print("Incorrect Syntax: -h or --help for more information")
print("rustserverautoupdate.py -c <Path to Configuration INI> [-s <Section Name - Used for multiple instances>]\n")
sys.exit(2)
for opt, arg in opts:
if opt in ("-h", "--help"):
argumenthelp()
sys.exit()
elif opt in ("-c", "--configpath"):
configPath = arg
elif opt in ("-s", "--section"):
sectionName = arg
if not configPath.strip():
configPath = configPath.strip()
if not sectionName.strip():
sectionName = "SERVER1"
signal.signal(signal.SIGTERM, signal_handler)
signal.signal(signal.SIGINT, signal_handler)
rm = RustMonitor('')
rm.main()
rm.main()

if __name__ == "__main__":
main(sys.argv[1:])
11 changes: 9 additions & 2 deletions RustServerAutoUpdate/RustServerAutoUpdate.pyproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>760be93c-44b6-486f-8e5d-c6a64c5224ff</ProjectGuid>
<ProjectHome>.</ProjectHome>
<StartupFile>RustServerAutoUpdate.py</StartupFile>
<StartupFile>rustserverautoupdate.py</StartupFile>
<SearchPath>
</SearchPath>
<WorkingDirectory>.</WorkingDirectory>
Expand Down Expand Up @@ -34,7 +34,10 @@
<Compile Include="rustbots\__init__.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="RustServerAutoUpdate.py" />
<Compile Include="rustserverautoupdate.py" />
<Compile Include="setup.py">
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Interpreter Include="..\..\..\..\..\.virtualenvs\RustServerAutoUpdate-WMf8rdv8\">
Expand All @@ -50,6 +53,10 @@
<ItemGroup>
<Folder Include="rustbots\" />
</ItemGroup>
<ItemGroup>
<Content Include="LICENSE.txt" />
<Content Include="README.md" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Python Tools\Microsoft.PythonTools.targets" />
<!-- Uncomment the CoreCompile target to enable the Build command in
Visual Studio and specify your pre- and post-build commands in
Expand Down
14 changes: 11 additions & 3 deletions RustServerAutoUpdate/rustbots/discord.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

class ServerInformation:
def __init__(self, gameName, serverName, serverIP, serverHostName = ""):
"""Information on the Server when sending message"""
"""Information on the Server when sending message
These items can all be empty strings, but they provide
detailed information about the server for display on Discord."""
self.gameName = gameName
self.serverName = serverName
self.serverIP = serverIP
Expand All @@ -13,12 +15,18 @@ def __init__(self, gameName, serverName, serverIP, serverHostName = ""):
class DiscordBot:
"""Bot to Send Message to Discord Server Using Webhook"""
def __init__(self, webHook, botName, botAvatar = ""):
"""Setup reusable bot information"""
"""Setup reusable bot information
webHook from Discord Bot Setup. Should be URL.
botName is not required, but will be displayed as user on Discord.
botAvatar allows custom user icon to be displayed. URL."""
self.webHook = webHook
self.botName = botName
self.botAvatar = botAvatar
def send_message(self, ServerInformation, message, title = "🚧 ALERT"):
"""Send message and title to discord server"""
"""Send message and title to discord server
ServerInformation comes from class and is required.
message is what should be said by discord bot.
title can be anything, but is used as an indicator for type of message."""
headers = {"Content-Type" : "application/json"}
jsonDict = {"username": self.botName,
"avatar_url": self.botAvatar,
Expand Down
1 change: 0 additions & 1 deletion RustServerAutoUpdate/rustbots/oxide.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ def get_latest_url(self, linux = True, gitJSONString = ""):

def get_running_version(self):
"""Get running version from local logs"""
#pattern = "(Loaded extension Rust v)([0-9]\.[0-9]\.(\d+))"
pattern = "Loaded extension Rust v(\d+\.\d+\.\d+)"
lastMatch = '0.0.0'
logFileNameList = glob.glob(os.path.join(self.oxideLogDir, 'oxide*.txt'))
Expand Down
4 changes: 4 additions & 0 deletions RustServerAutoUpdate/rustbots/rcon.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ def __init__(self, password, ip = "127.0.0.1", port = "28016", botName = "RustPy
self.botName = botName

def send_message(self, command, identifier = "-1", timeout = 10):
"""Send Message to Rust RCON. Return reply from server.
Example send_message('say Welcome to my Server')
Optionally send identifer and timeout. Identifier is a return for
certain commands to allow tracking. Timeout is how long to wait for reply."""
jsonDict = {"Identifier": identifier,
"Message": command,
"Name": self.botName}
Expand Down
22 changes: 22 additions & 0 deletions RustServerAutoUpdate/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import setuptools

with open("README.md", "r") as fh:
long_description = fh.read()

setuptools.setup(
name="rustserverautoupdate-Dateranoth",
version="0.0.1",
author="Dateranoth",
author_email="[email protected]",
description="A package to update rust when Oxide updates. Optionall send message to Discord or RCON",
long_description=long_description,
long_description_content_type="text/markdown",
url="https://github.com/dateranoth/rustserverautoupdatepython",
packages=setuptools.find_packages(),
classifiers=[
"Programming Language :: Python :: 3",
"License :: MIT License",
"Operating System :: OS Independent",
],
python_requires='>=3.7',
)

0 comments on commit 510272b

Please sign in to comment.