330 lines
12 KiB
Python
330 lines
12 KiB
Python
# This is WebJammies, it retrieves music from servers!
|
|
# It's like radio, but better!
|
|
# WebJammies is very easy to set up!
|
|
# It uses simple HTTP(S) and INI files as a sort DB
|
|
import requests
|
|
import time
|
|
import os
|
|
import shutil
|
|
# FIXME: Just for testing, take out later:
|
|
import urllib3
|
|
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
|
# FIXME: Just for testing!
|
|
try:
|
|
from discordrp import Presence
|
|
richpresense = True
|
|
except ImportError:
|
|
print("You don't have `discordrp` installed! Disabling Discord Rich Presence.")
|
|
richpresense = False
|
|
try:
|
|
import pygame
|
|
except ImportError:
|
|
print("Fatal! You need to install the `pygame` module to use WebJammies!")
|
|
exit(1)
|
|
|
|
|
|
class MusicPlayer:
|
|
def __init__(self):
|
|
self.discordrp: DiscordRP = None
|
|
self.nextfile = "song0.mp3"
|
|
self.nextmeta = None
|
|
self.looping = False
|
|
self.server = None
|
|
self.mixer = pygame.mixer
|
|
self.mixer.init()
|
|
|
|
def play_audio_file(self, _file=None):
|
|
if not _file and not self.nextfile:
|
|
return
|
|
if not _file:
|
|
self.discordrp.set_drp(self.nextmeta, self.server)
|
|
self.mixer.music.load(self.nextfile)
|
|
self.mixer.music.play()
|
|
print(
|
|
f"Currently playing: {self.nextmeta}\n"
|
|
"Press <Ctrl>+<C> to open the menu!"
|
|
)
|
|
paused = False
|
|
while True:
|
|
try:
|
|
if not self.mixer.music.get_busy() and not paused:
|
|
return
|
|
while self.mixer.music.get_busy():
|
|
time.sleep(0.1)
|
|
except KeyboardInterrupt:
|
|
print(
|
|
"\n"
|
|
f"Currently listening to: {self.nextmeta}\n"
|
|
"Here's some things you can do while listening:\n"
|
|
"[1] Play / Pause\n"
|
|
"[2] Skip\n"
|
|
"[3] Previous song\n"
|
|
"[4] Stop\n"
|
|
"[5] Close this menu (return to listening)\n"
|
|
"[6] Stop looping music"
|
|
)
|
|
choice = int(input())
|
|
if choice == 1:
|
|
if not paused:
|
|
paused = True
|
|
self.mixer.music.pause()
|
|
print(
|
|
f"Currently paused: {self.nextmeta}\n"
|
|
"Press <Ctrl>+<C> to open the menu and start playing again!"
|
|
)
|
|
else:
|
|
paused = False
|
|
self.mixer.music.unpause()
|
|
print(
|
|
f"Currently playing: {self.nextmeta}\n"
|
|
"Press <Ctrl>+<C> to open the menu!"
|
|
)
|
|
continue
|
|
elif choice == 2:
|
|
# figure smth out.
|
|
pass
|
|
elif choice == 3:
|
|
# same thing.
|
|
pass
|
|
elif choice == 4:
|
|
self.mixer.music.stop()
|
|
return
|
|
elif choice == 5:
|
|
print(
|
|
f"Currently playing: {self.nextmeta}\n"
|
|
"Press <Ctrl>+<C> to open the menu!"
|
|
)
|
|
continue
|
|
elif choice == 6:
|
|
if self.looping is False:
|
|
print("Can't stop looping music when we're not looping!")
|
|
continue
|
|
else:
|
|
self.mixer.music.stop()
|
|
self.looping = False
|
|
return
|
|
else:
|
|
self.discordrp.set_drp(_file, "localfile")
|
|
self.mixer.music.load(_file)
|
|
self.mixer.music.play()
|
|
while self.mixer.music.get_busy():
|
|
print(
|
|
"Currently listening to: localfile\n"
|
|
"Here's some things you can do while listening:\n"
|
|
"[1] Pause\n"
|
|
"[2] Skip\n"
|
|
"[3] Previous song\n"
|
|
"[4] Stop"
|
|
)
|
|
choice = input()
|
|
|
|
|
|
class MusicGetter:
|
|
def __init__(self):
|
|
self.musicplayer = None
|
|
self.server = None
|
|
self.discordrp = None
|
|
self.cursong_idx = 0
|
|
self.maxidx = None
|
|
self.songs = []
|
|
self.metadata = {}
|
|
print("Welcome to WebJammies!")
|
|
print("Checking some things...")
|
|
if richpresense is True:
|
|
self.discordrp = DiscordRP()
|
|
print("Discord Rich Presence enabled!")
|
|
else:
|
|
self.discordrp = DiscordRP()
|
|
# We still init it to prevent any bad code thingys
|
|
print("Discord Rich Presence not active.")
|
|
print("Initializing MusicPlayer...")
|
|
if os.path.exists("webjammies_temp"):
|
|
shutil.rmtree("webjammies_temp")
|
|
os.mkdir("webjammies_temp")
|
|
os.chdir("webjammies_temp")
|
|
self.musicplayer = MusicPlayer()
|
|
self.musicplayer.discordrp = self.discordrp
|
|
|
|
def get_server(self):
|
|
server = input("Enter the server of choice: ")
|
|
self.server = server
|
|
content = requests.get(f"{server}/webjammies/index.ini", verify=False)
|
|
text = content.text.splitlines()
|
|
append_to_songs = False
|
|
append_to_meta = False
|
|
for line in text:
|
|
if line.startswith("#"):
|
|
continue
|
|
elif line == "[FILES]":
|
|
append_to_songs = True
|
|
continue
|
|
elif line == "[META]":
|
|
append_to_songs = False
|
|
append_to_meta = True
|
|
i_since = 0
|
|
elif line == "[EOF]":
|
|
break
|
|
elif append_to_songs is True:
|
|
self.songs.append(f"{line}")
|
|
elif append_to_meta is True:
|
|
self.metadata[f"{self.songs[i_since]}"] = line
|
|
i_since += 1
|
|
else:
|
|
print("This server is not a WebJammies server! Please enter the correct server.")
|
|
exit(1)
|
|
self.maxidx = len(self.songs)
|
|
print("Loaded server configuration.")
|
|
|
|
def download_song(self, song):
|
|
content = requests.get(f"{self.server}/webjammies/{song}", verify=False)
|
|
with open("song0.mp3", "wb") as f:
|
|
f.write(content.content)
|
|
self.musicplayer.nextmeta = self.metadata.get(song)
|
|
|
|
def menu(self):
|
|
self.discordrp.default_drp()
|
|
if self.server is None:
|
|
print(
|
|
"\n"
|
|
"Whatcha wanna do?\n"
|
|
"[1] Connect to a server\n"
|
|
"[2] Start playing audio\n"
|
|
"[5] Loop music\n"
|
|
"[6] Exit"
|
|
)
|
|
else:
|
|
print(
|
|
"\n"
|
|
f"Currently you're connected to: {self.server}\n"
|
|
"Whatcha wanna do?\n"
|
|
"[1] Connect to a different server\n"
|
|
"[2] Start playing audio\n"
|
|
"[3] Choose a song\n"
|
|
"[4] Show whole playlist\n"
|
|
"[5] Loop music\n"
|
|
"[6] Exit"
|
|
)
|
|
# TODO: add some error checking
|
|
choice = int(input())
|
|
if choice == 1:
|
|
self.get_server()
|
|
print("MusicPlayer is loading the new configuration...")
|
|
self.musicplayer.server = self.server
|
|
self.download_song(self.songs[0])
|
|
self.cursong_idx += 1
|
|
return
|
|
|
|
elif choice == 2:
|
|
print("")
|
|
if self.server is None:
|
|
print("Cannot play music without a server!")
|
|
return
|
|
self.musicplayer.play_audio_file()
|
|
# automatically retrieve the next file after playing.
|
|
self.download_song(self.songs[self.cursong_idx])
|
|
# if we've reached the end of the list of songs, just wrap to 0
|
|
if self.cursong_idx >= self.maxidx:
|
|
self.cursong_idx = 0
|
|
else:
|
|
self.cursong_idx += 1
|
|
return
|
|
|
|
elif choice == 3:
|
|
print("")
|
|
print("Enter some details about the song to listen to!")
|
|
song = input()
|
|
for key, value in self.metadata.items():
|
|
if song.lower() in value.lower():
|
|
print(
|
|
"We might have a match!\n"
|
|
f"Is the song you're looking for: {value}?"
|
|
)
|
|
choice = input("You can enter 'y' for yes, 'n' for no.\n")
|
|
if choice.lower() == "y":
|
|
# I know this is stupid, but I really just wanna make sure it works :'(
|
|
song_idx = self.songs.index(key)
|
|
self.download_song(self.songs[song_idx])
|
|
self.musicplayer.play_audio_file()
|
|
break
|
|
elif choice.lower() == "n":
|
|
print("Aww shucks! We'll keep looking!")
|
|
continue
|
|
else:
|
|
print("Uuh, that wasn't what we were expecting!")
|
|
return
|
|
else:
|
|
print("Bad news, we couldn't find anything! :(")
|
|
return
|
|
return
|
|
|
|
elif choice == 4:
|
|
print("")
|
|
print(f"Alrighty! Here's the whole playlist from the server {self.server}")
|
|
for value in self.metadata.values():
|
|
print(f"{value}")
|
|
print("And that's all!")
|
|
return
|
|
|
|
elif choice == 5:
|
|
print("")
|
|
# TODO: make this better
|
|
if self.server is None:
|
|
print("Cannot play music without a server!")
|
|
return
|
|
self.musicplayer.looping = True
|
|
while self.musicplayer.looping:
|
|
self.musicplayer.play_audio_file()
|
|
self.download_song(self.songs[self.cursong_idx])
|
|
if self.cursong_idx >= self.maxidx:
|
|
self.cursong_idx = 0
|
|
self.download_song(self.songs[self.cursong_idx])
|
|
else:
|
|
self.cursong_idx += 1
|
|
return
|
|
|
|
elif choice == 6:
|
|
exit(0)
|
|
|
|
|
|
class DiscordRP:
|
|
def __init__(self):
|
|
self.client_id = "1346549750555476018"
|
|
try:
|
|
self.presence = Presence(self.client_id)
|
|
except Exception:
|
|
print("Error! Could not connect to Discord! Make sure Discord is active!")
|
|
print("Disabling presence...")
|
|
self.presence = None
|
|
self.default_drp()
|
|
|
|
def default_drp(self):
|
|
if self.presence is None:
|
|
return
|
|
self.presence.set(
|
|
{
|
|
"name": "WebJammies",
|
|
"type": 2,
|
|
"details": "Not jamming at the moment",
|
|
"state": "Looking for a server",
|
|
"timestamps": {"start": int(time.time())}
|
|
}
|
|
)
|
|
|
|
def set_drp(self, song, server):
|
|
if self.presence is None:
|
|
return
|
|
self.presence.set(
|
|
{
|
|
"name": "WebJammies",
|
|
"type": 2,
|
|
"details": f"Jamming to {song}!",
|
|
"state": f"Found on server: {server}",
|
|
"timestamps": {"start": int(time.time())}
|
|
}
|
|
)
|
|
|
|
if __name__ == "__main__":
|
|
m = MusicGetter()
|
|
while True:
|
|
m.menu()
|