forked from SirDank/dank.serverbuilder
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdank.serverbuilder.py
420 lines (299 loc) · 17.5 KB
/
dank.serverbuilder.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
# Note: dank.serverbuilder.py is meant to be run as an .exe by default, if you would like to execute the script, make the below changes...
# - uncomment the following line > filepath = os.path.dirname(__file__) # as .py
# - comment the following line > filepath = os.path.dirname(sys.argv[0]) # as .exe
import os
import re
import sys
import time
import random
import zipfile
import requests
import concurrent.futures
from colorama import init, Fore, Style
#filepath = os.path.dirname(__file__) # as .py
filepath = os.path.dirname(sys.argv[0]) # as .exe
os.chdir(filepath)
init(autoreset=True)
white = Fore.WHITE + Style.BRIGHT
magenta = Fore.MAGENTA + Style.BRIGHT
red = Fore.RED + Style.BRIGHT
cyan = Fore.CYAN + Style.BRIGHT
green = Fore.GREEN + Style.BRIGHT
yellow = Fore.YELLOW + Style.BRIGHT
# print banner
banner_ascii = '''
____ _ _____ _____ _ _ _ ___
| \ ___ ___| |_ | __|___ ___ _ _ ___ ___| __ |_ _|_| |_| |___ ___ |_ |
| | | .'| | '_|_|__ | -_| _| | | -_| _| __ -| | | | | . | -_| _| | _|
|____/|__,|_|_|_,_|_|_____|___|_| \_/|___|_| |_____|___|_|_|___|___|_| |___|
'''
# randomized banner color
bad_colors = ['BLACK', 'WHITE', 'LIGHTBLACK_EX', 'LIGHTWHITE_EX', 'RESET']
codes = vars(Fore)
colors = [codes[color] for color in codes if color not in bad_colors]
colored_chars = [random.choice(colors) + char for char in banner_ascii]
banner_ascii_colored = ''.join(colored_chars).splitlines()
# colored banner aligner
def aligner(banner, banner_colored):
width = os.get_terminal_size().columns
banner_lines = banner.splitlines()
for i in range(len(banner_lines)):
banner_lines[i] = banner_lines[i].center(width).replace(banner_lines[i],banner_colored[i])
banner_aligned = ''.join(banner_lines)
return banner_aligned
os.system('cls')
print(aligner(banner_ascii, banner_ascii_colored))
# get available papermc versions and print
Success = False
while not Success:
try:
response = requests.get("https://papermc.io/api/v2/projects/paper/").json()
available_versions = f"\n {white}> {magenta}Available Paper Versions{white}: {magenta}" + str(response['versions']).replace("[","").replace("]","").replace("\'","").replace(".",f"{white}.{magenta}").replace(",",f"{white},{magenta}")
print(available_versions)
available_versions = available_versions.replace(f"{white}","").replace(f"{magenta}","")
Success = True
except:
wait = input(f"\n {white}> {red}Failed to get paper versions! Make sure you are connected to the Internet! Press {white}Enter {red}to try again.")
# user input
name = str(input(f"\n {white}> {magenta}Server Name{white}: {magenta}"))
version = str(input(f"\n {white}> {magenta}Version{white}: {magenta}"))
# check if mc version is available
versions_list = available_versions.replace(",","").replace(f"{white}","").replace(f"{magenta}","").split(" ")
version_available = False
def version_check():
for ver in versions_list:
if version == ver:
global version_available
version_available = True
version_check()
# user input [ server settings ]
while not version_available:
print(f"\n {white}> {red}That version is not supported{white}!")
version = str(input(f"\n {white}> {magenta}Version{white}: {magenta}"))
version_check()
os.system(f"title dank.serverbuilder [ {name} - {version} ]")
ram = int(input(f"\n {white}> {magenta}RAM in MB {white}[ {magenta}Above 512 {white}]: {magenta}"))
if ram < 512:ram = 512
offline = str(input(f"\n {white}> {magenta}Allow Cracked Players {white}[ {magenta}y {white}/ {magenta}n {white}]: {magenta}"))
read_me = f'''
::::::::: :::::::::: ::: ::::::::: :::: :::: ::::::::::
:+: :+: :+: :+: :+: :+: :+: +:+:+: :+:+:+ :+:
+:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+:+ +:+ +:+
+#++:++#: +#++:++# +#++:++#++: +#+ +:+ +#+ +:+ +#+ +#++:++#
+#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+
#+# #+# #+# #+# #+# #+# #+# #+# #+# #+#
### ### ########## ### ### ######### ### ### ##########
'''
read_me_colored = read_me.replace(":",f"{white}:").replace("+",f"{white}+").replace("#",f"{magenta}#").splitlines()
os.system('cls')
sys.stdout.write(aligner(read_me, read_me_colored))
# JDK input
print(f"\n {white}> {magenta}The below program step is {white}required {magenta}to run a minecraft paper server of version 1{white}.{magenta}18 and above!")
print(f"\n {white}> {magenta}Only needs to be installed once!")
print(f"\n {white}> {magenta}If you do not know / are unsure / never installed JDK, type {white}\"{magenta}y{white}\"")
download_jdk = str(input(f"\n {white}> {magenta}Do you want to download {white}OpenJDK-17{magenta}? {white}[ {magenta}y {white}/ {magenta}n {white}]: {magenta}")).lower()
os.system('cls')
sys.stdout.write(aligner(read_me, read_me_colored))
# hosting method
print(f"\n {white}> {magenta}Great! Now you need to pick a {white}host{magenta} for your mc server{white}!")
print(f"\n {white}> {magenta}If you are {white}experienced {magenta}and would like to skip playit.gg and use {white}port forwarding {magenta}/ {white}alternative hosting methods, {magenta}Choose {white}Option 1{magenta}.")
print(f"\n {white}> {magenta}If you are {white}new {magenta}to hosting and would like to quickly host a server with {white}playit.gg{magenta}'s tunnel, Choose {white}Option 2{magenta}.")
playit = int(input(f"\n {white}> {magenta}Choice {white}[ {magenta}1 {white}/ {magenta}2 {white}]: {magenta}"))
if playit == 2:playit = True
else:playit = False
# go to workspace
original_name = name
try:os.mkdir(name)
except:
print(f"\n {white}> {red}The folder {white}{name} {red}already exists thus can't be created{white}! {red}Creating {white}{name}_new{red}...")
name+= "_new"
os.mkdir(name)
os.system(f"explorer.exe \"{name}\"")
os.chdir(name)
# begin download phase
os.system('cls')
print(f"\n {white}> {magenta}Preparing Downloads{white}...")
# download & extract dsb_assets.zip from github
data = requests.get("https://github.com/SirDankenstien/dank.serverbuilder/raw/main/assets/dsb_assets.zip", allow_redirects=True).content
open("dsb_assets.zip","wb").write(data)
zipfile.ZipFile(f"dsb_assets.zip", 'r').extractall()
time.sleep(3)
os.remove("dsb_assets.zip")
to_download_urls = []
to_download_filenames = []
def downloader(url, filename):
Success = False
while not Success:
try:
data = requests.get(url, allow_redirects=True).content
open(filename,"wb").write(data)
data = ""
print(f"\n {white}> {magenta}Completed {white}{filename}{magenta}!")
Success = True
except:
retry = input(f"\n {white}> {red}Failed {white}{filename}{red}! Press {white}ENTER {red}to try again!")
# EssentialsX.jar
response = requests.get(f"https://api.github.com/repos/EssentialsX/Essentials/releases").json()
build = str(response[0]['tag_name'])
to_download_urls.append(f"https://github.com/EssentialsX/Essentials/releases/download/{build}/EssentialsX-{build}.jar")
to_download_filenames.append(f"plugins\EssentialsX-{build}.jar")
# EssentialsXChat.jar
to_download_urls.append(f"https://github.com/EssentialsX/Essentials/releases/download/{build}/EssentialsXChat-{build}.jar")
to_download_filenames.append(f"plugins\EssentialsXChat-{build}.jar")
# EssentialsXSpawn.jar
to_download_urls.append(f"https://github.com/EssentialsX/Essentials/releases/download/{build}/EssentialsXSpawn-{build}.jar")
to_download_filenames.append(f"plugins\EssentialsXSpawn-{build}.jar")
# ProtocolLib.jar
to_download_urls.append("https://ci.dmulloy2.net/job/ProtocolLib/lastSuccessfulBuild/artifact/target/ProtocolLib.jar")
to_download_filenames.append(f"plugins\ProtocolLib.jar")
# TAB.jar
response = requests.get("https://api.github.com/repos/NEZNAMY/TAB/releases").json()
to_download_urls.append(str(response[0]['assets'][0]['browser_download_url']))
to_download_filenames.append(f"plugins\TAB.jar")
# BetterSleeping.jar
response = requests.get("https://api.github.com/repos/Nuytemans-Dieter/BetterSleeping/releases").json()
to_download_urls.append(str(response[0]['assets'][0]['browser_download_url']))
to_download_filenames.append(f"plugins\BetterSleeping.jar")
# ActionHealth.jar
response = requests.get("https://api.github.com/repos/zeshan321/ActionHealth/releases").json()
to_download_urls.append(str(response[0]['assets'][0]['browser_download_url']))
to_download_filenames.append(f"plugins\ActionHealth.jar")
# paperclip.jar
build = requests.get(f"https://papermc.io/api/v2/projects/paper/versions/{version}").json()
build = str(build['builds'][-1])
to_download_urls.append(f"https://papermc.io/api/v2/projects/paper/versions/{version}/builds/{build}/downloads/paper-{version}-{build}.jar")
to_download_filenames.append("paperclip.jar")
# playit.gg tunnel prorgram
if playit:
response = requests.get("https://playit.gg/download/")
url = re.findall("https://playit.gg/downloads/playit-win[a-zA-Z0-9._-]+",str(response.content.decode()))
playit_filename = str(url[0]).split('/')[-1]
to_download_urls.append(str(url[0]))
to_download_filenames.append(playit_filename)
# OpenJDK.msi
if download_jdk == "y":
random_ua = str(random.choice(list(set(requests.get("https://raw.githubusercontent.com/DavidWittman/requests-random-user-agent/master/requests_random_user_agent/useragents.txt").content.decode().splitlines()))))
headers = {"Host": "api.adoptium.net","Connection": "keep-alive","Cache-Control": "max-age=0","Upgrade-Insecure-Requests": "1","User-Agent": random_ua,"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9","Sec-Fetch-Site": "none","Sec-Fetch-Mode": "navigate","Sec-Fetch-User": "?1","Sec-Fetch-Dest": "document","Accept-Encoding": "gzip, deflate, br","Accept-Language": "en-US,en;q=0.9","X-Requested-With": "XMLHttpRequest"}
response = requests.get("https://api.adoptium.net/v3/assets/feature_releases/17/ga?architecture=x64&heap_size=normal&image_type=jdk&jvm_impl=hotspot&os=windows&page=0&page_size=10&project=jdk&sort_method=DEFAULT&sort_order=DESC&vendor=eclipse", headers=headers).json()
installer_url = str(response[0]["binaries"][0]["installer"]["link"])
jdk_filename = installer_url.split("/")[-1]
to_download_urls.append(installer_url)
to_download_filenames.append(jdk_filename)
# log4j exploit patch
log4j = f'''
{red}888 {yellow} d8888 {red} 888 888 888
{red}888 {yellow} d8P888 {red} 888 888 888
{red}888 {yellow} d8P 888 {red} 888 888 888
{red}888 .d88b. .d88b. {yellow} d8P 888 {red}.d8888b 88888b. .d88b. 888 888
{red}888 d88""88b d88P"88b {yellow}d88 888 {red}88K 888 "88b d8P Y8b 888 888
{red}888 888 888 888 888 {yellow}8888888888 {red}"Y8888b. 888 888 88888888 888 888
{red}888 Y88..88P Y88b 888 {yellow} 888 {red} X88 888 888 Y8b. 888 888
{red}88888888 "Y88P" "Y88888 {yellow} 888 {red} 88888P' 888 888 "Y8888 888 888
{red} 888
{red} Y8b d88P
{red} "Y88P"
'''
if "1.17" or "1.18" in version:extra_flag = "-Dlog4j2.formatMsgNoLookups=true "
elif "1.12" or "1.13" or "1.14" or "1.15" or "1.16" in version:extra_flag = "-Dlog4j.configurationFile=log4j2_112-116.xml "
elif "1.7" or "1.8" or "1.9" or "1.10" or "1.11" in version:extra_flag = "-Dlog4j.configurationFile=log4j2_17-111.xml "
else:extra_flag = ""
# begin downloads
print(f"\n {white}> {magenta}Starting Multiple Downloads{white}... [ {magenta}this might take a minute {white}]")
start_time = time.time()
futures = []
executor = concurrent.futures.ThreadPoolExecutor(max_workers=2)
for i in range(len(to_download_urls)):
futures.append(executor.submit(downloader, to_download_urls[i], to_download_filenames[i]))
for future in concurrent.futures.as_completed(futures):
try:future.result()
except:pass
futures.clear()
time_taken = ( time.time() - start_time ) / 60
os.system('cls')
print(f"\n {white}> {magenta}Finished All Downloads in {white}{{0:.1f}} {magenta}minutes{white}!".format(time_taken))
print(f"\n {white}> {magenta}Updating {white}server.properties")
# updating server.properties
data = open("server.properties","r").read().replace("motd=A Minecraft Server",f"motd=\\u00A7a---\\u00A76>\\u00A7b\\u00A7l {original_name} \\u00A76<\\u00A7a---\\u00A7r\\n \\u00A76\\u00A7l\\u00A7m-----\\u00A79\\u00A78\\u00A7l[\\u00A75 Made with \\u00A7ddank\\u00A7f.\\u00A7dserverbuilder \\u00A78\\u00A7l]\\u00A76\\u00A7l\\u00A7m-----")
if offline == "y":
data.replace("online-mode=true","online-mode=false")
open("server.properties","w").write(data)
print(f"\n {white}> {magenta}Creating batch scripts...")
# Creating .cmd(s)
data = f'''@echo off
color 0a
title Minecraft Server Console [ {name} ]
java -Xms512M -Xmx{ram}M -XX:+UseG1GC -XX:+UnlockExperimentalVMOptions -XX:MaxGCPauseMillis=100 -XX:+DisableExplicitGC -XX:TargetSurvivorRatio=90 -XX:G1NewSizePercent=50 -XX:G1MaxNewSizePercent=80 -XX:G1MixedGCLiveThresholdPercent=50 -XX:+AlwaysPreTouch {extra_flag}-jar paperclip.jar -nogui
pause
'''
open("start_server.cmd","w").write(data)
data = f'''#!/bin/sh
java -Xms512M -Xmx{ram}M -XX:+UseG1GC -XX:+UnlockExperimentalVMOptions -XX:MaxGCPauseMillis=100 -XX:+DisableExplicitGC -XX:TargetSurvivorRatio=90 -XX:G1NewSizePercent=50 -XX:G1MaxNewSizePercent=80 -XX:G1MixedGCLiveThresholdPercent=50 -XX:+AlwaysPreTouch {extra_flag}-jar paperclip.jar -nogui
'''
open("start_server.sh","wb").write(data.encode().replace(b'\r\n',b'\n'))
if playit:
data = f'''@echo off
color 0a
title Minecraft Java Playit.gg Tunnel [ {name} ] Keep me running to allow players to join your server!
{playit_filename}
pause
'''
open("start_tunnel.cmd","w").write(data)
time.sleep(5)
# log4j notice
os.system('cls')
sys.stdout.write(aligner(log4j.replace(red,"").replace(yellow,""), log4j.splitlines()))
print(f"\n {white}> {magenta}Minecraft servers built with {white}dank.serverbuilder {magenta}are protected from the {red}log{yellow}4{red}shell {magenta}exploit!")
time.sleep(10)
os.system('cls')
# begin installation phase
if download_jdk == "y":
print(f"\n {white}> {magenta}Starting {white}OpenJDK-16.msi")
time.sleep(3)
try:
os.startfile(jdk_filename)
except:
print(f"\n {white}> {red}Failed! Please run {white}{jdk_filename} {red}manually!")
temp = str(input(f"\n {white}> {magenta}Once you have sucessfully installed and closed {white}OpenJDK-16 {magenta}hit {white}[ {magenta}enter {white}] {magenta}to delete the installer{white}: {magenta}"))
os.remove(jdk_filename)
os.system('cls')
sys.stdout.write(aligner(read_me, read_me_colored))
# one-time setup
if playit:
print(f"\n {white}> {magenta}To allow players to connect to your server you first need to create a tunnel.")
print(f"\n {white}> {magenta}Follow the steps on {white}imgur {magenta}and complete the {white}one-time setup{magenta}.")
print(f"\n {white}> {magenta}If it does not open, please go to {white}https://imgur.com/a/W30s7bw {magenta}and {white}https://playit.gg/manage {magenta}manually.")
print(f"\n {white}> {magenta}Opening in 10s...")
time.sleep(10)
os.system("start https://imgur.com/a/W30s7bw")
time.sleep(10)
os.system("start https://playit.gg/manage")
print(f"\n {white}> {magenta}To start your server, run {white}start_server.cmd")
print(f"\n {white}> {magenta}To start your tunnel so people can connect over the internet, run {white}start_tunnel.cmd")
wait = input(f"\n {white}> {magenta}After you have read the above and created a tunnel, press {white}[ ENTER ] ")
else:
print(f"\n {white}> {magenta}As you have not selected {white}playit.gg{magenta}, To allow players to connect to your server over the internet, follow this tutorial on {white}port forwarding.")
open_youtube = str(input(f" {white}> {magenta}Do you want to open {white}port forwarding tutorial {magenta}on {white}youtube{magenta}? {white}[ {magenta}y {white}/ {magenta}n {white}]: {magenta}")).lower()
if open_youtube == "y":os.system("start https://youtu.be/X75GbRaGzu8")
# done!
os.system(f"title dank.serverbuilder [ complete! ]")
complete = f'''
___ ___ _ ____ _____ _ __
/ __|/ _ \ '__\ \ / / _ \ '__|
\__ \ __/ | \ V / __/ |
|___/\___|_| \_/ \___|_|
_ _
___ _ __ ___ __ _| |_(_) ___ _ __
/ __| '__/ _ \/ _` | __| |/ _ \| '_ \
| (__| | | __/ (_| | |_| | (_) | | | |
\___|_| \___|\__,_|\__|_|\___/|_| |_|
_ _ _
___ ___ _ __ ___ _ __ | | ___| |_ ___ / \\
/ __/ _ \| '_ ` _ \| '_ \| |/ _ \ __/ _ \/ /
| (_| (_) | | | | | | |_) | | __/ || __/\_/
\___\___/|_| |_| |_| .__/|_|\___|\__\___\/
|_|
'''
os.system('cls')
sys.stdout.write(aligner(complete, (red + complete).splitlines()))
time.sleep(3)
os.system("start https://allmylinks.com/sir-dankenstein")