Strip down docker container size
All checks were successful
Build and Publish / build_and_publish (push) Successful in 4m1s
All checks were successful
Build and Publish / build_and_publish (push) Successful in 4m1s
This commit is contained in:
parent
01e3e85f19
commit
d46ef03ba1
7 changed files with 101 additions and 56 deletions
95
Dockerfile
95
Dockerfile
|
@ -1,4 +1,4 @@
|
||||||
FROM python:3.11-slim
|
FROM python:3.12
|
||||||
|
|
||||||
LABEL org.opencontainers.image.source https://git.i-am.nexus/nex/college-bot-v2
|
LABEL org.opencontainers.image.source https://git.i-am.nexus/nex/college-bot-v2
|
||||||
LABEL org.opencontainers.image.url https://git.i-am.nexus/nex/college-bot-v2
|
LABEL org.opencontainers.image.url https://git.i-am.nexus/nex/college-bot-v2
|
||||||
|
@ -11,50 +11,50 @@ WORKDIR /app
|
||||||
RUN DEBIAN_FRONTEND=noninteractive apt-get update
|
RUN DEBIAN_FRONTEND=noninteractive apt-get update
|
||||||
|
|
||||||
# Install chrome dependencies
|
# Install chrome dependencies
|
||||||
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
#RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||||
webext-ublock-origin-chromium \
|
#webext-ublock-origin-chromium \
|
||||||
gconf-service \
|
#gconf-service \
|
||||||
libasound2 \
|
#libasound2 \
|
||||||
libatk1.0-0 \
|
#libatk1.0-0 \
|
||||||
libc6 \
|
#libc6 \
|
||||||
libcairo2 \
|
#libcairo2 \
|
||||||
libcups2 \
|
#libcups2 \
|
||||||
libdbus-1-3 \
|
#libdbus-1-3 \
|
||||||
libexpat1 \
|
#libexpat1 \
|
||||||
libfontconfig1 \
|
#libfontconfig1 \
|
||||||
libgcc1 \
|
#libgcc1 \
|
||||||
libgconf-2-4 \
|
#libgconf-2-4 \
|
||||||
libgdk-pixbuf2.0-0 \
|
#libgdk-pixbuf2.0-0 \
|
||||||
libglib2.0-0 \
|
#libglib2.0-0 \
|
||||||
libgtk-3-0 \
|
#libgtk-3-0 \
|
||||||
libnspr4 \
|
#libnspr4 \
|
||||||
libpango-1.0-0 \
|
#libpango-1.0-0 \
|
||||||
libpangocairo-1.0-0 \
|
#libpangocairo-1.0-0 \
|
||||||
libstdc++6 \
|
#libstdc++6 \
|
||||||
libx11-6 \
|
#libx11-6 \
|
||||||
libx11-xcb1 \
|
#libx11-xcb1 \
|
||||||
libxcb1 \
|
#libxcb1 \
|
||||||
libxcomposite1 \
|
#libxcomposite1 \
|
||||||
libxcursor1 \
|
#libxcursor1 \
|
||||||
libxdamage1 \
|
#libxdamage1 \
|
||||||
libxext6 \
|
#libxext6 \
|
||||||
libxfixes3 \
|
#libxfixes3 \
|
||||||
libxi6 \
|
#libxi6 \
|
||||||
libxrandr2 \
|
#libxrandr2 \
|
||||||
libxrender1 \
|
#libxrender1 \
|
||||||
libxss1 \
|
#libxss1 \
|
||||||
libxtst6 \
|
#libxtst6 \
|
||||||
ca-certificates \
|
#ca-certificates \
|
||||||
fonts-liberation \
|
#fonts-liberation \
|
||||||
libappindicator1 \
|
#libappindicator1 \
|
||||||
libnss3 \
|
#libnss3 \
|
||||||
lsb-release \
|
#lsb-release \
|
||||||
xdg-utils
|
#xdg-utils
|
||||||
|
#
|
||||||
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
#RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||||
chromium-common \
|
# chromium-common \
|
||||||
chromium-driver \
|
# chromium-driver \
|
||||||
chromium-sandbox
|
# chromium-sandbox
|
||||||
|
|
||||||
# Install general utilities
|
# Install general utilities
|
||||||
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||||
|
@ -67,11 +67,6 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||||
curl \
|
curl \
|
||||||
libmagic-dev
|
libmagic-dev
|
||||||
|
|
||||||
# Install image dependencies
|
|
||||||
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
|
||||||
ffmpeg \
|
|
||||||
imagemagick
|
|
||||||
|
|
||||||
RUN python3 -m venv /app/venv
|
RUN python3 -m venv /app/venv
|
||||||
RUN /app/venv/bin/pip install --upgrade --no-input pip wheel setuptools
|
RUN /app/venv/bin/pip install --upgrade --no-input pip wheel setuptools
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,11 @@ services:
|
||||||
- ./jimmy.log:/app/jimmy.log
|
- ./jimmy.log:/app/jimmy.log
|
||||||
- /dev/dri:/dev/dri
|
- /dev/dri:/dev/dri
|
||||||
- jimmy-data:/app/data
|
- jimmy-data:/app/data
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
- /etc/timezone:/etc/timezone:ro
|
||||||
|
- /usr/bin/nmap:/usr/bin/nmap:ro
|
||||||
|
- /usr/bin/ffmpeg:/usr/bin/ffmpeg:ro
|
||||||
|
- /usr/bin/ffprobe:/usr/bin/ffprobe:ro
|
||||||
extra_hosts:
|
extra_hosts:
|
||||||
- host.docker.internal:host-gateway
|
- host.docker.internal:host-gateway
|
||||||
depends_on:
|
depends_on:
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
|
# In order to use commands in this system, the following things must be installed (ideally in /usr/local/bin):
|
||||||
|
# - `ffmpeg`, usually `ffmpeg`, sometimes `ffmpeg-full`.
|
||||||
|
# - /dev/dri should be passed through to the container for hardware acceleration.
|
||||||
|
# - `ffprobe`, usually `ffmpeg`, sometimes `ffmpeg-full`.
|
||||||
|
# In docker, you can just bind these as volumes, and read-only too.
|
||||||
import asyncio
|
import asyncio
|
||||||
import io
|
import io
|
||||||
|
import shutil
|
||||||
import typing
|
import typing
|
||||||
from collections.abc import Iterable
|
from collections.abc import Iterable
|
||||||
import logging
|
import logging
|
||||||
|
@ -105,6 +111,12 @@ class AutoResponder(commands.Cog):
|
||||||
:param uri: The URI to transcode
|
:param uri: The URI to transcode
|
||||||
:return: A transcoded file
|
:return: A transcoded file
|
||||||
"""
|
"""
|
||||||
|
if not shutil.which("ffmpeg"):
|
||||||
|
self.log.error("ffmpeg not installed")
|
||||||
|
return
|
||||||
|
if not shutil.which("ffprobe"):
|
||||||
|
self.log.error("ffprobe not installed")
|
||||||
|
return
|
||||||
last_reaction: str | None = None
|
last_reaction: str | None = None
|
||||||
|
|
||||||
def update_reaction(new: str | None = None) -> None:
|
def update_reaction(new: str | None = None) -> None:
|
||||||
|
@ -118,9 +130,7 @@ class AutoResponder(commands.Cog):
|
||||||
last_reaction = new
|
last_reaction = new
|
||||||
self.log.info("Waiting for transcode lock to release")
|
self.log.info("Waiting for transcode lock to release")
|
||||||
async with self.transcode_lock:
|
async with self.transcode_lock:
|
||||||
cog: FFMeta = self.bot.get_cog("FFMeta")
|
cog = FFMeta(self.bot)
|
||||||
if not cog:
|
|
||||||
raise RuntimeError("FFMeta cog not loaded")
|
|
||||||
if not isinstance(uri, str):
|
if not isinstance(uri, str):
|
||||||
uri = str(uri)
|
uri = str(uri)
|
||||||
|
|
||||||
|
@ -240,6 +250,12 @@ class AutoResponder(commands.Cog):
|
||||||
*domains: str,
|
*domains: str,
|
||||||
additional: Iterable[str] = None
|
additional: Iterable[str] = None
|
||||||
) -> None:
|
) -> None:
|
||||||
|
if not shutil.which("ffmpeg"):
|
||||||
|
self.log.error("ffmpeg not installed")
|
||||||
|
return
|
||||||
|
if not shutil.which("ffprobe"):
|
||||||
|
self.log.error("ffprobe not installed")
|
||||||
|
return
|
||||||
if self.allow_hevc_to_h264 is False:
|
if self.allow_hevc_to_h264 is False:
|
||||||
self.log.debug("hevc_to_h264 is disabled, not engaging.")
|
self.log.debug("hevc_to_h264 is disabled, not engaging.")
|
||||||
return
|
return
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
This module is only meant to be loaded during election times.
|
This module is only meant to be loaded during election times.
|
||||||
"""
|
"""
|
||||||
import asyncio
|
import asyncio
|
||||||
import datetime
|
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,14 @@
|
||||||
|
# In order to use commands in this system, the following things must be installed (ideally in /usr/local/bin):
|
||||||
|
# - `ffmpeg`, usually `ffmpeg`, sometimes `ffmpeg-full`.
|
||||||
|
# - /dev/dri should be passed through to the container for hardware acceleration.
|
||||||
|
# - `ffprobe`, usually `ffmpeg`, sometimes `ffmpeg-full`.
|
||||||
|
# In docker, you can just bind these as volumes, and read-only too.
|
||||||
import asyncio
|
import asyncio
|
||||||
import io
|
import io
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import pathlib
|
import pathlib
|
||||||
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import typing
|
import typing
|
||||||
|
@ -56,6 +62,8 @@ class FFMeta(commands.Cog):
|
||||||
@commands.slash_command()
|
@commands.slash_command()
|
||||||
async def ffprobe(self, ctx: discord.ApplicationContext, url: str = None, attachment: discord.Attachment = None):
|
async def ffprobe(self, ctx: discord.ApplicationContext, url: str = None, attachment: discord.Attachment = None):
|
||||||
"""Runs ffprobe on a given URL or attachment"""
|
"""Runs ffprobe on a given URL or attachment"""
|
||||||
|
if not shutil.which("ffprobe"):
|
||||||
|
return await ctx.respond("ffprobe is not installed on this system.")
|
||||||
if url is None:
|
if url is None:
|
||||||
if attachment is None:
|
if attachment is None:
|
||||||
return await ctx.respond("No URL or attachment provided")
|
return await ctx.respond("No URL or attachment provided")
|
||||||
|
@ -142,6 +150,10 @@ class FFMeta(commands.Cog):
|
||||||
] = False,
|
] = False,
|
||||||
):
|
):
|
||||||
"""Converts a given URL or attachment to an Opus file"""
|
"""Converts a given URL or attachment to an Opus file"""
|
||||||
|
if not shutil.which("ffmpeg"):
|
||||||
|
return await ctx.respond("ffmpeg is not installed on this system.")
|
||||||
|
if not shutil.which("ffprobe"):
|
||||||
|
return await ctx.respond("ffprobe is not installed on this system.")
|
||||||
if bitrate == 0:
|
if bitrate == 0:
|
||||||
bitrate = 0.5
|
bitrate = 0.5
|
||||||
if mono:
|
if mono:
|
||||||
|
@ -244,6 +256,8 @@ class FFMeta(commands.Cog):
|
||||||
rbh = Path("assets/right-behind-you.ogg").resolve()
|
rbh = Path("assets/right-behind-you.ogg").resolve()
|
||||||
if not rbh.exists():
|
if not rbh.exists():
|
||||||
return await ctx.respond("The file `right-behind-you.ogg` is missing.")
|
return await ctx.respond("The file `right-behind-you.ogg` is missing.")
|
||||||
|
if not shutil.which("ffmpeg"):
|
||||||
|
return await ctx.respond("ffmpeg is not installed on this system.")
|
||||||
if not image.content_type.startswith("image"):
|
if not image.content_type.startswith("image"):
|
||||||
return await ctx.respond("That's not an image!")
|
return await ctx.respond("That's not an image!")
|
||||||
with tempfile.NamedTemporaryFile(suffix=Path(image.filename).suffix) as temp:
|
with tempfile.NamedTemporaryFile(suffix=Path(image.filename).suffix) as temp:
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
# In order to use commands in this system, the following things must be installed (ideally in /usr/local/bin):
|
||||||
|
# - `ping`, usually iputils-ping
|
||||||
|
# - `whois`, usually whois
|
||||||
|
# - `traceroute`, usually traceroute
|
||||||
|
# - `nmap`, usually nmap
|
||||||
|
# In docker, you can just bind these as volumes, and read-only too.
|
||||||
import asyncio
|
import asyncio
|
||||||
import io
|
import io
|
||||||
import json
|
import json
|
||||||
|
@ -49,6 +55,8 @@ class NetworkCog(commands.Cog):
|
||||||
@commands.slash_command()
|
@commands.slash_command()
|
||||||
async def ping(self, ctx: discord.ApplicationContext, target: str = None):
|
async def ping(self, ctx: discord.ApplicationContext, target: str = None):
|
||||||
"""Get the bot's latency, or the network latency to a target."""
|
"""Get the bot's latency, or the network latency to a target."""
|
||||||
|
if not shutil.which("ping"):
|
||||||
|
return await ctx.respond("Ping is not installed on this system.")
|
||||||
if target is None:
|
if target is None:
|
||||||
return await ctx.respond(f"Pong! {round(self.bot.latency * 1000)}ms")
|
return await ctx.respond(f"Pong! {round(self.bot.latency * 1000)}ms")
|
||||||
else:
|
else:
|
||||||
|
@ -75,6 +83,8 @@ class NetworkCog(commands.Cog):
|
||||||
@commands.slash_command()
|
@commands.slash_command()
|
||||||
async def whois(self, ctx: discord.ApplicationContext, target: str):
|
async def whois(self, ctx: discord.ApplicationContext, target: str):
|
||||||
"""Get information about a user."""
|
"""Get information about a user."""
|
||||||
|
if not shutil.which("whois"):
|
||||||
|
return await ctx.respond("Whois is not installed on this system.")
|
||||||
|
|
||||||
async def run_command(with_disclaimer: bool = False):
|
async def run_command(with_disclaimer: bool = False):
|
||||||
args = [] if with_disclaimer else ["-H"]
|
args = [] if with_disclaimer else ["-H"]
|
||||||
|
@ -221,6 +231,8 @@ class NetworkCog(commands.Cog):
|
||||||
await ctx.defer()
|
await ctx.defer()
|
||||||
if re.search(r"\s+", url):
|
if re.search(r"\s+", url):
|
||||||
return await ctx.respond("URL cannot contain spaces.")
|
return await ctx.respond("URL cannot contain spaces.")
|
||||||
|
if not shutil.which("traceroute"):
|
||||||
|
return await ctx.respond("Traceroute is not installed on this system.")
|
||||||
|
|
||||||
args = ["sudo", "-E", "-n", "traceroute"]
|
args = ["sudo", "-E", "-n", "traceroute"]
|
||||||
flags = {
|
flags = {
|
||||||
|
|
|
@ -3,6 +3,7 @@ import functools
|
||||||
import hashlib
|
import hashlib
|
||||||
import logging
|
import logging
|
||||||
import math
|
import math
|
||||||
|
import shutil
|
||||||
import time
|
import time
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
|
@ -190,6 +191,8 @@ class YTDLCog(commands.Cog):
|
||||||
:param file: The file to convert
|
:param file: The file to convert
|
||||||
:return: The converted file
|
:return: The converted file
|
||||||
"""
|
"""
|
||||||
|
if not shutil.which("ffmpeg"):
|
||||||
|
raise RuntimeError("ffmpeg is not installed.")
|
||||||
new_file = file.with_suffix(".m4a")
|
new_file = file.with_suffix(".m4a")
|
||||||
args = [
|
args = [
|
||||||
"-vn",
|
"-vn",
|
||||||
|
@ -319,8 +322,9 @@ class YTDLCog(commands.Cog):
|
||||||
else:
|
else:
|
||||||
chosen_format = user_format
|
chosen_format = user_format
|
||||||
|
|
||||||
|
ffmpeg_installed = bool(shutil.which("ffmpeg"))
|
||||||
options.setdefault("postprocessors", [])
|
options.setdefault("postprocessors", [])
|
||||||
if audio_only:
|
if audio_only and ffmpeg_installed:
|
||||||
# Overwrite format here to be best audio under 25 megabytes.
|
# Overwrite format here to be best audio under 25 megabytes.
|
||||||
chosen_format = "ba[filesize<20M]"
|
chosen_format = "ba[filesize<20M]"
|
||||||
# Also force sorting by the best audio bitrate first.
|
# Also force sorting by the best audio bitrate first.
|
||||||
|
@ -332,7 +336,7 @@ class YTDLCog(commands.Cog):
|
||||||
options["format"] = chosen_format
|
options["format"] = chosen_format
|
||||||
options["paths"] = paths
|
options["paths"] = paths
|
||||||
|
|
||||||
if subtitles:
|
if subtitles and ffmpeg_installed:
|
||||||
subtitles, burn = subtitles.split("+", 1) if "+" in subtitles else (subtitles, "0")
|
subtitles, burn = subtitles.split("+", 1) if "+" in subtitles else (subtitles, "0")
|
||||||
burn = burn[0].lower() in ("y", "1", "t")
|
burn = burn[0].lower() in ("y", "1", "t")
|
||||||
if subtitles.lower() == "auto":
|
if subtitles.lower() == "auto":
|
||||||
|
|
Loading…
Reference in a new issue