wi1-bot 2.0.1__tar.gz → 2.0.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wi1_bot-2.0.3/.dockerignore +25 -0
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/.github/workflows/docker.yaml +3 -1
- wi1_bot-2.0.3/Dockerfile +36 -0
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/PKG-INFO +2 -1
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/README.md +1 -0
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/compose.yaml +3 -2
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/wi1_bot/discord/bot.py +10 -12
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/wi1_bot/discord/cogs/movie.py +2 -3
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/wi1_bot/discord/cogs/series.py +4 -3
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/wi1_bot/transcoder/transcode_queue.py +2 -1
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/wi1_bot/transcoder/transcoder.py +14 -2
- wi1_bot-2.0.1/.dockerignore +0 -9
- wi1_bot-2.0.1/Dockerfile +0 -32
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/.envrc +0 -0
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/.github/workflows/pypi-publish.yml +0 -0
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/.gitignore +0 -0
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/.pre-commit-config.yaml +0 -0
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/LICENSE +0 -0
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/config.yaml.template +0 -0
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/flake.nix +0 -0
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/pyproject.toml +0 -0
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/tests/movie_downloaded.py +0 -0
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/uv.lock +0 -0
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/wi1_bot/__init__.py +0 -0
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/wi1_bot/arr/__init__.py +0 -0
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/wi1_bot/arr/download.py +0 -0
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/wi1_bot/arr/episode.py +0 -0
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/wi1_bot/arr/movie.py +0 -0
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/wi1_bot/arr/radarr.py +0 -0
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/wi1_bot/arr/sonarr.py +0 -0
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/wi1_bot/arr/util.py +0 -0
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/wi1_bot/config.py +0 -0
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/wi1_bot/discord/__init__.py +0 -0
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/wi1_bot/discord/cogs/__init__.py +0 -0
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/wi1_bot/discord/helpers.py +0 -0
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/wi1_bot/push.py +0 -0
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/wi1_bot/scripts/__init__.py +0 -0
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/wi1_bot/scripts/add_tag.py +0 -0
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/wi1_bot/scripts/rescan.py +0 -0
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/wi1_bot/scripts/start.py +0 -0
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/wi1_bot/scripts/transcode_item.py +0 -0
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/wi1_bot/transcoder/__init__.py +0 -0
- {wi1_bot-2.0.1 → wi1_bot-2.0.3}/wi1_bot/webhook.py +0 -0
@@ -0,0 +1,25 @@
|
|
1
|
+
.DS_Store
|
2
|
+
.direnv/
|
3
|
+
.dockerignore
|
4
|
+
.envrc
|
5
|
+
.git/
|
6
|
+
.github/
|
7
|
+
.gitignore
|
8
|
+
.mypy_cache/
|
9
|
+
.pre-commit-config.yaml
|
10
|
+
.ruff_cache/
|
11
|
+
.venv/
|
12
|
+
.vscode/
|
13
|
+
Dockerfile
|
14
|
+
compose.yaml
|
15
|
+
flake.lock
|
16
|
+
flake.nix
|
17
|
+
|
18
|
+
config.yaml
|
19
|
+
tests/files/
|
20
|
+
log/
|
21
|
+
|
22
|
+
build/
|
23
|
+
dist/
|
24
|
+
*.egg-info/
|
25
|
+
_version.py
|
wi1_bot-2.0.3/Dockerfile
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
FROM linuxserver/ffmpeg:latest AS base
|
2
|
+
|
3
|
+
RUN apt-get update && apt-get install -yqq --no-install-recommends python3
|
4
|
+
|
5
|
+
FROM base AS builder
|
6
|
+
|
7
|
+
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
|
8
|
+
ENV UV_PYTHON_DOWNLOADS=0 UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy
|
9
|
+
|
10
|
+
WORKDIR /app
|
11
|
+
|
12
|
+
COPY pyproject.toml uv.lock .
|
13
|
+
|
14
|
+
RUN --mount=type=cache,target=/root/.cache/uv uv sync --locked --no-install-project --no-dev
|
15
|
+
|
16
|
+
COPY . .
|
17
|
+
|
18
|
+
RUN --mount=type=cache,target=/root/.cache/uv uv sync --locked --no-dev
|
19
|
+
|
20
|
+
FROM base
|
21
|
+
|
22
|
+
COPY --from=builder --chown=app:app /app /app
|
23
|
+
ENV PATH="/app/.venv/bin:$PATH"
|
24
|
+
|
25
|
+
LABEL org.opencontainers.image.source="https://github.com/wthueb/wi1-bot"
|
26
|
+
LABEL org.opencontainers.image.maintainer="wilhueb@gmail.com"
|
27
|
+
|
28
|
+
ENV WB_CONFIG_PATH=/config/config.yaml
|
29
|
+
ENV WB_LOG_DIR=/logs
|
30
|
+
|
31
|
+
RUN mkdir -p /config
|
32
|
+
RUN mkdir -p /logs
|
33
|
+
|
34
|
+
EXPOSE 9000
|
35
|
+
|
36
|
+
ENTRYPOINT ["python", "-m", "wi1_bot.scripts.start"]
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: wi1-bot
|
3
|
-
Version: 2.0.
|
3
|
+
Version: 2.0.3
|
4
4
|
Summary: Discord bot for Radarr/Sonarr integration
|
5
5
|
Project-URL: Homepage, https://github.com/wthueb/wi1-bot
|
6
6
|
Author-email: William Huebner <wilhueb@gmail.com>
|
@@ -39,6 +39,7 @@ Requires Python >=3.11.
|
|
39
39
|
|
40
40
|
### TODO
|
41
41
|
|
42
|
+
- use overseerr for search/requests
|
42
43
|
- use sqlite
|
43
44
|
- dynamically copy streams
|
44
45
|
- i.e. if mov_text in input, -c:s srt
|
@@ -9,14 +9,15 @@ services:
|
|
9
9
|
devices:
|
10
10
|
- capabilities:
|
11
11
|
- gpu
|
12
|
+
devices:
|
13
|
+
- /dev/dri:/dev/dri
|
12
14
|
environment:
|
13
15
|
- WB_CONFIG_PATH=/data/config.yaml
|
14
16
|
- WB_LOG_PATH=/data/logs
|
17
|
+
- MONGODB_CONNECTION_STRING=mongodb://mongodb:27017
|
15
18
|
volumes:
|
16
19
|
- .:/data
|
17
20
|
|
18
21
|
mongodb:
|
19
22
|
container_name: mongodb
|
20
23
|
image: mongo:8.0
|
21
|
-
ports:
|
22
|
-
- 27017:27017
|
@@ -1,7 +1,6 @@
|
|
1
1
|
import asyncio
|
2
2
|
import logging
|
3
3
|
import traceback
|
4
|
-
from typing import Any
|
5
4
|
|
6
5
|
import discord
|
7
6
|
from discord.ext import commands
|
@@ -21,12 +20,14 @@ sonarr = Sonarr(config["sonarr"]["url"], config["sonarr"]["api_key"])
|
|
21
20
|
|
22
21
|
|
23
22
|
@bot.check
|
24
|
-
async def check_channel(ctx: commands.Context[
|
23
|
+
async def check_channel(ctx: commands.Context[commands.Bot]) -> bool:
|
25
24
|
return ctx.channel.id == config["discord"]["channel_id"]
|
26
25
|
|
27
26
|
|
28
27
|
@bot.event
|
29
|
-
async def on_command_error(
|
28
|
+
async def on_command_error(
|
29
|
+
ctx: commands.Context[commands.Bot], error: commands.CommandError
|
30
|
+
) -> None:
|
30
31
|
match error:
|
31
32
|
case commands.CommandNotFound() | commands.CheckFailure():
|
32
33
|
pass
|
@@ -63,13 +64,13 @@ async def on_ready() -> None:
|
|
63
64
|
|
64
65
|
|
65
66
|
@bot.before_invoke
|
66
|
-
async def before_invoke(ctx: commands.Context[
|
67
|
+
async def before_invoke(ctx: commands.Context[commands.Bot]) -> None:
|
67
68
|
logger.info(f"got command from {ctx.message.author}: {ctx.message.content}")
|
68
69
|
|
69
70
|
|
70
71
|
@bot.command(name="downloads", aliases=["queue", "q"], help="see the status of movie downloads")
|
71
72
|
@commands.cooldown(1, 10)
|
72
|
-
async def downloads_cmd(ctx: commands.Context[
|
73
|
+
async def downloads_cmd(ctx: commands.Context[commands.Bot]) -> None:
|
73
74
|
async with ctx.typing():
|
74
75
|
queue = radarr.get_downloads() + sonarr.get_downloads()
|
75
76
|
|
@@ -84,7 +85,7 @@ async def downloads_cmd(ctx: commands.Context[Any]) -> None:
|
|
84
85
|
|
85
86
|
@bot.command(name="quota", help="see your used space on the plex")
|
86
87
|
@commands.cooldown(1, 60, commands.BucketType.user)
|
87
|
-
async def quota_cmd(ctx: commands.Context[
|
88
|
+
async def quota_cmd(ctx: commands.Context[commands.Bot]) -> None:
|
88
89
|
async with ctx.typing():
|
89
90
|
used = (
|
90
91
|
radarr.get_quota_amount(ctx.message.author.id)
|
@@ -98,17 +99,14 @@ async def quota_cmd(ctx: commands.Context[Any]) -> None:
|
|
98
99
|
|
99
100
|
pct = used / maximum * 100 if maximum != 0 else 100
|
100
101
|
|
101
|
-
msg = (
|
102
|
-
f"you have added {used:.2f}/{maximum:.2f} GB ({pct:.1f}%) of useless crap"
|
103
|
-
" to the plex"
|
104
|
-
)
|
102
|
+
msg = f"you have added {used:.2f}/{maximum:.2f} GB ({pct:.1f}%) of useless crap to the plex"
|
105
103
|
|
106
104
|
await reply(ctx.message, msg)
|
107
105
|
|
108
106
|
|
109
107
|
@bot.command(name="quotas", help="see everyone's used space on the plex")
|
110
108
|
@commands.cooldown(1, 60)
|
111
|
-
async def quotas_cmd(ctx: commands.Context[
|
109
|
+
async def quotas_cmd(ctx: commands.Context[commands.Bot]) -> None:
|
112
110
|
if "quotas" not in config["discord"]:
|
113
111
|
await reply(ctx.message, "quotas are not implemented here")
|
114
112
|
return
|
@@ -139,7 +137,7 @@ async def quotas_cmd(ctx: commands.Context[Any]) -> None:
|
|
139
137
|
|
140
138
|
@bot.command(name="addtag", help="add a user tag")
|
141
139
|
@commands.has_role("plex-admin")
|
142
|
-
async def addtag_cmd(ctx: commands.Context[
|
140
|
+
async def addtag_cmd(ctx: commands.Context[commands.Bot], name: str, user: discord.Member) -> None:
|
143
141
|
tag = f"{name}: {user.id}"
|
144
142
|
|
145
143
|
radarr.create_tag(tag)
|
@@ -1,6 +1,5 @@
|
|
1
1
|
import asyncio
|
2
2
|
import logging
|
3
|
-
from typing import Any
|
4
3
|
|
5
4
|
from discord.ext import commands
|
6
5
|
|
@@ -18,7 +17,7 @@ class MovieCog(commands.Cog):
|
|
18
17
|
self.radarr = Radarr(config["radarr"]["url"], config["radarr"]["api_key"])
|
19
18
|
|
20
19
|
@commands.command(name="addmovie", help="add a movie to the plex")
|
21
|
-
async def addmovie_cmd(self, ctx: commands.Context[
|
20
|
+
async def addmovie_cmd(self, ctx: commands.Context[commands.Bot], *, query: str = "") -> None:
|
22
21
|
if not query:
|
23
22
|
await reply(ctx.message, "usage: !addmovie KEYWORDS...")
|
24
23
|
return
|
@@ -71,7 +70,7 @@ class MovieCog(commands.Cog):
|
|
71
70
|
await ctx.send(f"hey <@!{config['discord']['admin_id']}> get this guy a tag")
|
72
71
|
|
73
72
|
@commands.command(name="delmovie", help="delete a movie from the plex")
|
74
|
-
async def delmovie_cmd(self, ctx: commands.Context[
|
73
|
+
async def delmovie_cmd(self, ctx: commands.Context[commands.Bot], *, query: str = "") -> None:
|
75
74
|
if not query:
|
76
75
|
await reply(ctx.message, "usage: !delmovie KEYWORDS...")
|
77
76
|
return
|
@@ -1,6 +1,5 @@
|
|
1
1
|
import asyncio
|
2
2
|
import logging
|
3
|
-
from typing import Any
|
4
3
|
|
5
4
|
from discord.ext import commands
|
6
5
|
|
@@ -19,7 +18,7 @@ class SeriesCog(commands.Cog):
|
|
19
18
|
|
20
19
|
@commands.command(name="addshow", help="add a show to the plex")
|
21
20
|
@commands.has_any_role("plex-admin", "plex-shows")
|
22
|
-
async def addshow_cmd(self, ctx: commands.Context[
|
21
|
+
async def addshow_cmd(self, ctx: commands.Context[commands.Bot], *, query: str = "") -> None:
|
23
22
|
if not query:
|
24
23
|
await reply(ctx.message, "usage: !addshow KEYWORDS...")
|
25
24
|
return
|
@@ -91,7 +90,9 @@ class SeriesCog(commands.Cog):
|
|
91
90
|
|
92
91
|
@commands.command(name="delshow", help="delete a show from the plex")
|
93
92
|
@commands.has_any_role("plex-admin", "plex-shows")
|
94
|
-
async def delshow_command(
|
93
|
+
async def delshow_command(
|
94
|
+
self, ctx: commands.Context[commands.Bot], *, query: str = ""
|
95
|
+
) -> None:
|
95
96
|
if not query:
|
96
97
|
await reply(ctx.message, "usage: !delshow KEYWORDS...")
|
97
98
|
return
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import os
|
1
2
|
from typing import Any, cast
|
2
3
|
|
3
4
|
from mongoengine import Document, connect
|
@@ -23,7 +24,7 @@ class TranscodeItem(Document):
|
|
23
24
|
|
24
25
|
class TranscodeQueue:
|
25
26
|
def __init__(self) -> None:
|
26
|
-
connect("wi1_bot", connect=
|
27
|
+
connect("wi1_bot", connect=True, host=os.environ.get("MONGODB_CONNECTION_STRING", None))
|
27
28
|
|
28
29
|
def add(
|
29
30
|
self,
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import logging
|
2
2
|
import pathlib
|
3
|
+
import re
|
3
4
|
import shlex
|
4
5
|
import shutil
|
5
6
|
import subprocess
|
@@ -14,6 +15,14 @@ from wi1_bot.config import config
|
|
14
15
|
|
15
16
|
from .transcode_queue import TranscodeItem, queue
|
16
17
|
|
18
|
+
# https://github.com/Radarr/Radarr/blob/e29be26fc9a5570bdf37a1b9504b3c0162be7715/src/NzbDrone.Core/Parser/Parser.cs#L134
|
19
|
+
CLEAN_RELEASE_GROUP_REGEX = re.compile(
|
20
|
+
r"(-(RP|1|NZBGeek|Obfuscated|Obfuscation|Scrambled|sample|Pre|postbot|xpost|Rakuv[a-z0-9]*|WhiteRev|BUYMORE|AsRequested|AlternativeToRequested|GEROV|Z0iDS3N|Chamele0n|4P|4Planet|AlteZachen|RePACKPOST))+",
|
21
|
+
re.IGNORECASE,
|
22
|
+
)
|
23
|
+
# https://github.com/Radarr/Radarr/blob/e29be26fc9a5570bdf37a1b9504b3c0162be7715/src/NzbDrone.Core/Parser/Parser.cs#L138
|
24
|
+
CLEAN_TORRENT_SUFFIX_REGEX = re.compile(r"\[(?:ettv|rartv|rarbg|cttv|publichd)\]", re.IGNORECASE)
|
25
|
+
|
17
26
|
|
18
27
|
class SignalInterrupt(Exception):
|
19
28
|
pass
|
@@ -76,7 +85,10 @@ class Transcoder:
|
|
76
85
|
tmp_folder = pathlib.Path("/tmp/wi1-bot")
|
77
86
|
tmp_folder.mkdir(exist_ok=True)
|
78
87
|
|
79
|
-
|
88
|
+
filename = path.stem
|
89
|
+
filename = CLEAN_RELEASE_GROUP_REGEX.sub("", filename)
|
90
|
+
filename = CLEAN_TORRENT_SUFFIX_REGEX.sub("", filename)
|
91
|
+
transcode_to = tmp_folder / f"{filename}-TRANSCODED.mkv"
|
80
92
|
|
81
93
|
command = self._build_ffmpeg_command(item, transcode_to)
|
82
94
|
|
@@ -273,4 +285,4 @@ class Transcoder:
|
|
273
285
|
if __name__ == "__main__":
|
274
286
|
logging.basicConfig(level=logging.DEBUG)
|
275
287
|
t = Transcoder()
|
276
|
-
t._worker()
|
288
|
+
t._worker() # pyright: ignore[reportPrivateUsage]
|
wi1_bot-2.0.1/.dockerignore
DELETED
wi1_bot-2.0.1/Dockerfile
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
FROM jrottenberg/ffmpeg:7.1-nvidia2404 AS base
|
2
|
-
|
3
|
-
RUN apt-get update && apt-get install -yqq --no-install-recommends python3
|
4
|
-
|
5
|
-
FROM base AS compiler
|
6
|
-
|
7
|
-
RUN apt-get install -yqq --no-install-recommends python3-venv git
|
8
|
-
|
9
|
-
RUN python3 -m venv /opt/venv
|
10
|
-
ENV PATH="/opt/venv/bin:$PATH"
|
11
|
-
|
12
|
-
WORKDIR /app
|
13
|
-
COPY . .
|
14
|
-
RUN pip install .
|
15
|
-
|
16
|
-
FROM base
|
17
|
-
|
18
|
-
COPY --from=compiler /opt/venv /opt/venv
|
19
|
-
ENV PATH="/opt/venv/bin:$PATH"
|
20
|
-
|
21
|
-
LABEL org.opencontainers.image.source="https://github.com/wthueb/wi1-bot"
|
22
|
-
LABEL org.opencontainers.image.maintainer="wilhueb@gmail.com"
|
23
|
-
|
24
|
-
ENV WB_CONFIG_PATH=/config/config.yaml
|
25
|
-
ENV WB_LOG_DIR=/logs
|
26
|
-
|
27
|
-
RUN mkdir -p /config
|
28
|
-
RUN mkdir -p /logs
|
29
|
-
|
30
|
-
EXPOSE 9000
|
31
|
-
|
32
|
-
ENTRYPOINT ["python", "-m", "wi1_bot.scripts.start"]
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|