Compare commits
3 commits
2039293245
...
3122d3a3e9
Author | SHA1 | Date | |
---|---|---|---|
3122d3a3e9 | |||
fe230bba6a | |||
ee3b15c29b |
8 changed files with 121 additions and 20 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,6 +1,7 @@
|
|||
.env
|
||||
.venv
|
||||
.cache/*
|
||||
cache/*
|
||||
.logs/*
|
||||
logs/*
|
||||
sounds/originals/*
|
||||
|
|
47
README.md
47
README.md
|
@ -22,31 +22,52 @@ Copy `.env.example` to `.env`:
|
|||
- Settings > Advanced > Developer Mode: enabled
|
||||
- Right click the guild and select "Copy ID"
|
||||
|
||||
- `DISCORD_STATUS_WEBHOOK_URL` (optional) is used to monitor when the bot fails
|
||||
- Channel Settings > Integrations > New Webhook (don't forget to save changes)
|
||||
- Copy Webhook URL
|
||||
|
||||
- `DISCORD_BOT_ADMIN_ROLE_ID` for reloading cogs
|
||||
- `DISCORD_BOT_ADMIN_USER_ID` for reloading cogs
|
||||
- `DISCORD_VCJOIN_CHANNEL` for the VCJoin cog
|
||||
|
||||
## Setup
|
||||
|
||||
### ...with PDM
|
||||
### with systemd
|
||||
|
||||
```sh
|
||||
pdm install --prod
|
||||
pdm run python app.py
|
||||
```
|
||||
mkdir -p /srv/discord
|
||||
cd /srv/discord
|
||||
|
||||
### ...with requirements.txt and virtualenv
|
||||
sudo useradd --system -s /srv/discord discord
|
||||
sudo chown -R discord:discord /srv/discord
|
||||
|
||||
```sh
|
||||
virtualenv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
python app.py
|
||||
sudo -Hu discord git clone https://git.trwnh.com/a/umi.git
|
||||
|
||||
python -m venv .venv
|
||||
.venv/bin/pip install -r umi/requirements.txt
|
||||
|
||||
sudo cp umi/umi@.service /etc/systemd/system/umi@.service
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl start umi@umi
|
||||
```
|
||||
|
||||
### ...with Docker Compose
|
||||
|
||||
```sh
|
||||
docker compose build
|
||||
docker compose up -d
|
||||
```
|
||||
mkdir -p /srv/discord
|
||||
cd /srv/discord
|
||||
|
||||
sudo useradd --system -s /srv/discord discord
|
||||
sudo chown -R discord:discord /srv/discord
|
||||
|
||||
sudo -Hu discord git clone https://git.trwnh.com/a/umi.git
|
||||
|
||||
cd umi
|
||||
sudo docker compose build
|
||||
sudo docker compose up -d
|
||||
```
|
||||
|
||||
## Log into YouTube
|
||||
|
||||
- Follow the instructions at https://github.com/yt-dlp/yt-dlp/wiki/Extractors#exporting-youtube-cookies
|
||||
- Put your extracted cookies into config/cookies.txt
|
0
cache/.gitkeep
vendored
Normal file
0
cache/.gitkeep
vendored
Normal file
|
@ -593,6 +593,65 @@ class Music(Cog):
|
|||
logger.info(f"Message sent: Playing {len(tracks)} tracks.")
|
||||
await self.play_next(ctx)
|
||||
|
||||
@command()
|
||||
async def ytlogin(self, ctx: Context):
|
||||
"""Print token and instructions for authorizing with YouTube"""
|
||||
logger.info(f".ytlogin")
|
||||
process = subprocess.Popen(
|
||||
[
|
||||
"yt-dlp",
|
||||
"--netrc",
|
||||
"--skip-download", # we don't care to actually download the video, we just wanna authorize
|
||||
"https://www.youtube.com/watch?v=dQw4w9WgXcQ" # this can be anything, it just needs a youtube URL
|
||||
],
|
||||
stdout=subprocess.PIPE,
|
||||
encoding="utf-8",
|
||||
)
|
||||
while True:
|
||||
line = process.stdout.readline()
|
||||
if not line:
|
||||
logger.debug("Subprocess ran out of lines in stdout")
|
||||
break
|
||||
if "google.com" in line:
|
||||
msg = await ctx.send(line)
|
||||
if msg:
|
||||
logger.info(f"Message sent: {line}")
|
||||
break
|
||||
timeout = time() + 30 # TODO: make this variable instead of hardcoded?
|
||||
while (process.poll() is None) and (time() < timeout):
|
||||
pass # this loop will break when the process exits with a return code, or when the timeout is exceeded
|
||||
if process.poll() is None:
|
||||
logger.debug("Process still hasn't exited yet, so we need to kill it and let the user know that the authorization process failed")
|
||||
process.kill()
|
||||
text = "Authorization process timed out."
|
||||
msg = await ctx.send(text)
|
||||
if msg:
|
||||
logger.info(f"Message sent: {text}")
|
||||
return
|
||||
else:
|
||||
logger.debug("Process has exited with a return code, so check if the return code indicates no errors.")
|
||||
if process.returncode == 0:
|
||||
text = "The process has finished with no errors, so you're probably logged in now."
|
||||
msg = await ctx.send(text)
|
||||
if msg:
|
||||
logger.info(f"Message sent: {text}")
|
||||
process.kill() # just in case
|
||||
return
|
||||
else:
|
||||
process.kill() # just in case
|
||||
out, err = process.communicate()
|
||||
if err:
|
||||
logger.error(f"An error occurred during the authorization process: {err}")
|
||||
msg = await ctx.send(
|
||||
f"An error occurred during the authorization process:\n",
|
||||
f"```\n",
|
||||
f"{err}",
|
||||
f"```",
|
||||
)
|
||||
if msg:
|
||||
logger.info(f"Message sent: An error occurred during the authorization process")
|
||||
return
|
||||
|
||||
@command(aliases=['p', 'listen'])
|
||||
async def play(self, ctx: Context, *, query: str = ""):
|
||||
"""Add track(s) to queue"""
|
||||
|
@ -864,11 +923,8 @@ ytdl_format_options = {
|
|||
"default_search": "auto",
|
||||
# "source_address": "0.0.0.0", # Bind to ipv4 since ipv6 addresses cause issues
|
||||
"extract_flat": True, # massive speedup for fetching metadata, at the cost of no upload date
|
||||
#"cookiefile": "cookies.txt",
|
||||
"cookiefile": "config/cookies.txt",
|
||||
"cachedir": "cache",
|
||||
"username": "oauth",
|
||||
"password": "",
|
||||
#"usenetrc": True,
|
||||
}
|
||||
username = getenv("YOUTUBE_USERNAME")
|
||||
password = getenv("YOUTUBE_PASSWORD")
|
||||
ytdl = youtube_dl.YoutubeDL(ytdl_format_options)
|
1
config/.netrc
Normal file
1
config/.netrc
Normal file
|
@ -0,0 +1 @@
|
|||
machine youtube login oauth password ""
|
7
contrib/notify.sh
Normal file
7
contrib/notify.sh
Normal file
|
@ -0,0 +1,7 @@
|
|||
#!/usr/bin/bash
|
||||
|
||||
curl \
|
||||
-X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"username": "system", "content": "'"$1"'"}' \
|
||||
$DISCORD_STATUS_WEBHOOK_URL
|
15
contrib/umi@.service
Normal file
15
contrib/umi@.service
Normal file
|
@ -0,0 +1,15 @@
|
|||
[Unit]
|
||||
Description=Discord bot for logging VC joins and playing music
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Restart=on-failure
|
||||
User=discord
|
||||
WorkingDirectory=/srv/discord/%I
|
||||
EnvironmentFile=/srv/discord/%I/.env
|
||||
ExecStart=/srv/discord/.venv/bin/python -u app.py
|
||||
ExecStopPost=/srv/discord/%I/notify.sh "umi instance stopped: `%i`"
|
||||
ExecStartPost=/srv/discord/%I/notify.sh "umi instance started: `%i`"
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -13,6 +13,6 @@ services:
|
|||
- ./cogs:/umi/cogs
|
||||
- ./sounds:/umi/sounds
|
||||
- ./logs:/umi/.logs
|
||||
- ./cookies.txt:/umi/cookies.txt
|
||||
- ./.netrc:/root/.netrc
|
||||
- ./config/cookies.txt:/umi/cookies.txt
|
||||
- ./config/.netrc:/root/.netrc
|
||||
- ./cache:/umi/cache
|
Loading…
Add table
Reference in a new issue