diff --git a/webjammies.py b/webjammies.py new file mode 100644 index 0000000..45ba2f6 --- /dev/null +++ b/webjammies.py @@ -0,0 +1,327 @@ +# 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 + 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 + to open the menu and start playing again!" + ) + else: + paused = False + self.mixer.music.unpause() + print( + f"Currently playing: {self.nextmeta}\n" + "Press + 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 + 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: + 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()