From 5db11730ac5833a9688e84120e5a327fc9f39725 Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Mon, 22 Aug 2022 19:20:11 +0000 Subject: [PATCH] add basic functionality mirrored from arthurbot --- .devcontainer/Dockerfile | 7 ++ .devcontainer/requirements.txt | 4 + .gitignore | 133 +++++++++++++++++++++++++++++++++ src/config.py | 62 +++++++++++++++ src/musicbot.py | 96 ++++++++++++++++++++++++ 5 files changed, 302 insertions(+) create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/requirements.txt create mode 100644 .gitignore create mode 100644 src/config.py create mode 100644 src/musicbot.py diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..0d215b8 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,7 @@ +FROM python:slim +WORKDIR / +RUN apt-get -y update; apt-get -y upgrade +RUN apt-get -y install git binutils xxd +RUN apt-get -y install python3 python3-dev git python3-pip python-is-python3 libgl1-mesa-dev build-essential ffmpeg +COPY requirements.txt . +RUN pip install -r requirements.txt \ No newline at end of file diff --git a/.devcontainer/requirements.txt b/.devcontainer/requirements.txt new file mode 100644 index 0000000..1d5d8f6 --- /dev/null +++ b/.devcontainer/requirements.txt @@ -0,0 +1,4 @@ +discord +PyNaCl +pytube +yt_dlp \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3511c61 --- /dev/null +++ b/.gitignore @@ -0,0 +1,133 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +**/*.json + +**/session/* \ No newline at end of file diff --git a/src/config.py b/src/config.py new file mode 100644 index 0000000..826a8c5 --- /dev/null +++ b/src/config.py @@ -0,0 +1,62 @@ +import json + +sample_json = """ +{ + "guild":{ + "token": "", + "prefix": "$", + "roleid": 0, + "username": "music-bot" + }, +} +""" + +def load_config(path, config_vector): + try: + f = open(path, "r") + config_vector.update(json.load(f)) + f.close() + return 0 + except: + f = open(path, "w") + f.write(sample_json) + f.close() + return 1 + +def save_config(path, config_vector): + f = open(path, "w") + json.dump(config_vector, f, ensure_ascii=False, indent=4) + f.close() + return 0 + +def get_token(config_path): + config_vector = {} + success = load_config(config_path, config_vector) + if success == 0: + return config_vector["guild"]["token"] + else: + return None + +def get_prefix(config_path): + config_vector = {} + success = load_config(config_path, config_vector) + if success == 0: + return config_vector["guild"]["prefix"] + else: + return None + +def get_roleid(config_path): + config_vector = {} + success = load_config(config_path, config_vector) + if success == 0: + return config_vector["guild"]["roleid"] + else: + return None + +def get_username(config_path): + config_vector = {} + success = load_config(config_path, config_vector) + if success == 0: + return config_vector["guild"]["username"] + else: + return None \ No newline at end of file diff --git a/src/musicbot.py b/src/musicbot.py new file mode 100644 index 0000000..86f1e4e --- /dev/null +++ b/src/musicbot.py @@ -0,0 +1,96 @@ +from asyncio import sleep +import discord +from discord.ext import commands +import yt_dlp +from config import * + +config_path = "config.json" + +ffmpeg_options = { + 'options': '-vn' +} + +token = get_token(config_path) + +async def determine_prefix(bot, message): + return get_prefix(config_path) + +intents = discord.Intents.default() +intents.members = True +intents.message_content = True +bot = commands.Bot(command_prefix = determine_prefix, description='very cool', intents = intents) + +@bot.event +async def on_ready(): + print('Logged in as {0} ({0.id})'.format(bot.user)) + print('------') + +@bot.command() +async def setprefix(ctx, *arg): + if(len(arg) != 1): + await ctx.send("usage: setprefix ") + + else: + prefix = arg[0] + + with open("prefix", "w") as f: + f.write(prefix) + f.close() + + await ctx.send("set prefix to: {0}".format(prefix)) + +@bot.command() +async def setrole(ctx, *arg: discord.Role): + if(len(arg) != 1): + await ctx.send("usage: setrole @") + + else: + roleid = arg[0].id + + with open("roleid", "w") as f: + f.write(str(roleid)) + f.close() + + await ctx.send("set followable role to {0}".format(arg[0])) + +@bot.command() +async def playmusic(ctx, *arg): + + ydl_opts = { + 'format': 'mp4', + 'quiet': True, + 'paths': { + 'home': './session/' + }, + 'outtmpl': { + 'default': '%(autonumber)s.%(ext)s', + }, + 'postprocessors': [{ + 'key': 'FFmpegExtractAudio', + }], + } + + try: + await ctx.voice_client.disconnect() + except: + pass + + url = arg[0] + + with yt_dlp.YoutubeDL(ydl_opts) as ydl: + info = ydl.extract_info(url, download=False) + duration = info.get('duration') + name = info.get('title') + if duration < 1200: + await ctx.send("downloading music requested: {0}".format(name)) + ydl.download([url]) + audio = "session/00001.m4a" + await ctx.author.voice.channel.connect() + ctx.voice_client.play(discord.FFmpegPCMAudio(audio), after=lambda e: print('Player error: %s' % e) if e else None) + while ctx.voice_client.is_playing(): + await sleep(0.01) + await ctx.voice_client.disconnect() + else: + await ctx.send("music requested was too long ({0} > 1200)".format(duration)) + +bot.run(token) \ No newline at end of file