Skip to content
This repository was archived by the owner on Apr 5, 2025. It is now read-only.

Commit d023c1f

Browse files
committed
Added __main__.py for downloading and installing Lavalink and Java.
1 parent 953adec commit d023c1f

File tree

1 file changed

+284
-0
lines changed

1 file changed

+284
-0
lines changed

wavelink/__main__.py

Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
"""MIT License
2+
3+
Copyright (c) 2019-2022 PythonistaGuild
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
22+
"""
23+
import argparse
24+
import asyncio
25+
import pathlib
26+
import sys
27+
import typing
28+
29+
import aiohttp
30+
31+
32+
parser = argparse.ArgumentParser()
33+
parser.add_argument('--java', action='store_true')
34+
35+
args = parser.parse_args()
36+
get_java = args.java
37+
38+
39+
RELEASES = 'https://api.github.com/repos/freyacodes/Lavalink/releases/latest'
40+
JAVA = 'https://download.oracle.com/java/17/archive/jdk-17.0.3.1_windows-x64_bin.exe'
41+
42+
43+
if get_java and sys.platform != 'win32':
44+
raise RuntimeError('Downloading and installing Java is only supported on Windows.')
45+
46+
if get_java:
47+
import ctypes
48+
import os
49+
50+
try:
51+
is_admin = os.getuid() == 0
52+
except AttributeError:
53+
is_admin = ctypes.windll.shell32.IsUserAnAdmin() != 0
54+
55+
if not is_admin:
56+
raise RuntimeError('This script requires administrator privileges to install Java.\n'
57+
'Please restart the script in Command Prompt or Powershell as an administrator.')
58+
59+
60+
_application_yml = """
61+
server: # REST and WS server
62+
port: {port}
63+
address: {address}
64+
lavalink:
65+
server:
66+
password: "{password}"
67+
sources:
68+
youtube: true
69+
bandcamp: true
70+
soundcloud: true
71+
twitch: true
72+
vimeo: true
73+
http: true
74+
local: false
75+
bufferDurationMs: 400 # The duration of the NAS buffer. Higher values fare better against longer GC pauses
76+
frameBufferDurationMs: 5000 # How many milliseconds of audio to keep buffered
77+
youtubePlaylistLoadLimit: 6 # Number of pages at 100 each
78+
playerUpdateInterval: 5 # How frequently to send player updates to clients, in seconds
79+
youtubeSearchEnabled: true
80+
soundcloudSearchEnabled: true
81+
gc-warnings: true
82+
#ratelimit:
83+
#ipBlocks: ["1.0.0.0/8", "..."] # list of ip blocks
84+
#excludedIps: ["...", "..."] # ips which should be explicit excluded from usage by lavalink
85+
#strategy: "RotateOnBan" # RotateOnBan | LoadBalance | NanoSwitch | RotatingNanoSwitch
86+
#searchTriggersFail: true # Whether a search 429 should trigger marking the ip as failing
87+
#retryLimit: -1 # -1 = use default lavaplayer value | 0 = infinity | >0 = retry will happen this numbers times
88+
89+
metrics:
90+
prometheus:
91+
enabled: false
92+
endpoint: /metrics
93+
94+
sentry:
95+
dsn: ""
96+
environment: ""
97+
# tags:
98+
# some_key: some_value
99+
# another_key: another_value
100+
101+
logging:
102+
file:
103+
max-history: 30
104+
max-size: 1GB
105+
path: ./logs/
106+
107+
level:
108+
root: INFO
109+
lavalink: INFO
110+
"""
111+
112+
113+
async def download(location: pathlib.Path, *, url: str) -> None:
114+
lavalink = None
115+
116+
async with aiohttp.ClientSession() as session:
117+
async with session.get(url=url) as head_resp:
118+
if url == RELEASES:
119+
120+
data = await head_resp.json()
121+
assets = data['assets']
122+
123+
for asset in assets:
124+
if asset['name'] == 'Lavalink.jar':
125+
126+
length = asset['size']
127+
lavalink = asset['browser_download_url']
128+
chunks = round(length / 1024)
129+
break
130+
else:
131+
length = head_resp.content_length
132+
chunks = round(length / 1024)
133+
134+
if lavalink:
135+
file = 'Lavalink.jar'
136+
url = lavalink
137+
else:
138+
file = 'java17.exe'
139+
140+
async with session.get(url=url) as resp:
141+
with open(f'{location.absolute()}/{file}', 'wb') as fp:
142+
count = 1
143+
144+
async for chunk in resp.content.iter_chunked(1024):
145+
x = int(40 * count / chunks)
146+
147+
print(f"\rDownloading {file}: [{u'█' * x}{('.' * (40 - x))}] "
148+
f"{count / 1024:.2f}/{chunks / 1024:.2f} MB",
149+
end='',
150+
file=sys.stdout,
151+
flush=True)
152+
153+
fp.write(chunk)
154+
count += 1
155+
156+
print("\n", flush=True, file=sys.stdout)
157+
158+
159+
def parse_input(value: str, type_: typing.Any) -> typing.Union[str, int, bool, None]:
160+
value = str(value)
161+
162+
quits = ('q', 'quit', 'exit')
163+
if value.lower() in quits:
164+
print('Exiting installer...')
165+
sys.exit(0)
166+
167+
if type_ is bool:
168+
169+
bools = {'y': True, 'yes': True, 'true': True, 'n': False, 'no': False, 'false': False}
170+
result = bools.get(value.lower(), None)
171+
172+
return result
173+
174+
try:
175+
result = type_(value.lower())
176+
except ValueError:
177+
return None
178+
179+
return result
180+
181+
182+
async def main():
183+
cwd = pathlib.Path.cwd()
184+
185+
print('\nEnter Q at anytime to quit the installer...\n')
186+
187+
while True:
188+
while True:
189+
190+
port = parse_input(input('Please enter the port number for Lavalink (Enter to use default: 2333): ')
191+
or 2333, int)
192+
193+
if not port:
194+
print('Invalid port specified. Please enter a number for your port. Enter Q to quit.')
195+
continue
196+
197+
break
198+
199+
while True:
200+
201+
address = parse_input(input('Please enter the address to star Lavalink (Enter to use default: 0.0.0.0): ')
202+
or '0.0.0.0', str)
203+
204+
if not address:
205+
print('Invalid address specified. Please enter a valid binding IP address. Enter Q to quit.')
206+
continue
207+
208+
break
209+
210+
while True:
211+
212+
password = parse_input(input('Please enter a password for Lavalink (Enter to use default:'
213+
' "youshallnotpass"): ')
214+
or 'youshallnotpass', str)
215+
216+
if not password:
217+
print('Invalid password specified. Please enter a valid password. Enter Q to quit.')
218+
continue
219+
220+
break
221+
222+
while True:
223+
224+
location = parse_input(input('Please enter a install directory. '
225+
'An attempt to create the directory will be made if it does not not exist. '
226+
f'(Enter to use the current directory: {cwd}): ')
227+
or cwd, str)
228+
229+
if not location:
230+
print('Invalid location specified. Please enter a valid directory. Enter Q to quit.')
231+
continue
232+
233+
location = pathlib.Path(location)
234+
235+
break
236+
237+
while True:
238+
confirmed_ = parse_input(input('\nPlease confirm the following information:\n\n'
239+
f'Port: {port}\nAddress:'
240+
f' {address}\nPassword:'
241+
f' "{password}"\nLocation:'
242+
f' {location.absolute()}\n\n'
243+
f'(Y: Confirm, N: Re-Enter, Q: Quit): '),
244+
bool)
245+
246+
if confirmed_ is None:
247+
print('Invalid response...')
248+
continue
249+
250+
break
251+
252+
if confirmed_ is True:
253+
break
254+
255+
if not location.exists():
256+
try:
257+
location.mkdir(parents=True, exist_ok=False)
258+
except Exception as e:
259+
print(f'Could make directory: "{location.absolute()}". {e}\nExiting the installer...')
260+
261+
await download(location=location, url=RELEASES)
262+
print('Lavalink successfully downloaded...')
263+
264+
with open(f'{location.absolute()}/application.yml', 'w') as fp:
265+
fp.write(_application_yml.format(port=port, address=address, password=password))
266+
267+
if get_java:
268+
await download(location=location, url=JAVA)
269+
270+
proc = await asyncio.subprocess.create_subprocess_exec(f'{location.absolute()}/java17.exe')
271+
await proc.wait()
272+
273+
print(f'\nSuccess!\n\nDownload Location: {location.absolute()}\n\nInstructions:\n'
274+
f'- Open a Powershell or Command Prompt\n'
275+
f'- cd {location.absolute()}\n'
276+
f'- java -jar Lavalink.jar\n\n'
277+
f'To connect use the following details:\n'
278+
f'Port : {port}\n'
279+
f'Password : "{password}"\n\n'
280+
f'You may change these values by editing the application.yml\n')
281+
282+
283+
if __name__ == '__main__':
284+
asyncio.run(main())

0 commit comments

Comments
 (0)