* Screenshot (unpolished, functional)
* Dig
* Traceroute
* Whois
* Ping
* yt-dl
* Docker file
This commit is contained in:
Nexus 2024-01-02 22:59:47 +00:00
parent 4c4ddbf6c1
commit fb705abf7c
8 changed files with 67 additions and 209 deletions

View file

@ -4,19 +4,12 @@
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="aa6d62a8-d64d-4a60-a85f-8d9fa52b6b49" name="Changes" comment="Update gitignore">
<change afterPath="$PROJECT_DIR$/.idea/college-bot-2.0.iml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/inspectionProfiles/profiles_settings.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/modules.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/vcs.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/cogs/net.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/cogs/screenshot.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/cogs/ytdl.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/config.example.toml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/main.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/requirements.txt" afterDir="false" />
<list default="true" id="aa6d62a8-d64d-4a60-a85f-8d9fa52b6b49" name="Changes" comment="Beta 1&#10;&#10;* Screenshot (unpolished, functional)&#10;* Dig&#10;* Traceroute&#10;* Whois&#10;* Ping&#10;* yt-dl">
<change afterPath="$PROJECT_DIR$/Dockerfile" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/cogs/screenshot.py" beforeDir="false" afterPath="$PROJECT_DIR$/cogs/screenshot.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/config.example.toml" beforeDir="false" afterPath="$PROJECT_DIR$/config.example.toml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/requirements.txt" beforeDir="false" afterPath="$PROJECT_DIR$/requirements.txt" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -78,7 +71,7 @@
<workItem from="1704140854074" duration="30000" />
<workItem from="1704140889356" duration="166000" />
<workItem from="1704141061129" duration="2495000" />
<workItem from="1704224862150" duration="9650000" />
<workItem from="1704224862150" duration="11351000" />
</task>
<task id="LOCAL-00001" summary="Update gitignore">
<option name="closed" value="true" />
@ -88,7 +81,15 @@
<option name="project" value="LOCAL" />
<updated>1704234449168</updated>
</task>
<option name="localTasksCounter" value="2" />
<task id="LOCAL-00002" summary="Beta 1&#10;&#10;* Screenshot (unpolished, functional)&#10;* Dig&#10;* Traceroute&#10;* Whois&#10;* Ping&#10;* yt-dl">
<option name="closed" value="true" />
<created>1704234565095</created>
<option name="number" value="00002" />
<option name="presentableId" value="LOCAL-00002" />
<option name="project" value="LOCAL" />
<updated>1704234565095</updated>
</task>
<option name="localTasksCounter" value="3" />
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
@ -97,6 +98,7 @@
<component name="VcsManagerConfiguration">
<option name="ADD_EXTERNAL_FILES_SILENTLY" value="true" />
<MESSAGE value="Update gitignore" />
<option name="LAST_COMMIT_MESSAGE" value="Update gitignore" />
<MESSAGE value="Beta 1&#10;&#10;* Screenshot (unpolished, functional)&#10;* Dig&#10;* Traceroute&#10;* Whois&#10;* Ping&#10;* yt-dl" />
<option name="LAST_COMMIT_MESSAGE" value="Beta 1&#10;&#10;* Screenshot (unpolished, functional)&#10;* Dig&#10;* Traceroute&#10;* Whois&#10;* Ping&#10;* yt-dl" />
</component>
</project>

16
Dockerfile Normal file
View file

@ -0,0 +1,16 @@
FROM python:3.11-bookworm
RUN DEBIAN_FRONTEND=noninteractive apt-get update
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y traceroute iputils-ping dnsutils net-tools git chromium chromium-driver chromium-sandbox chromium-shell
RUN pip install --upgrade --break-system-packages pip wheel setuptools
COPY requirements.txt /tmp/requirements.txt
RUN pip install -Ur /tmp/requirements.txt --break-system-packages --no-input
WORKDIR /app
COPY main.py /app
COPY cookies.txt /app
COPY cogs/ /app/cogs/
CMD ["python", "main.py"]

View file

@ -1,15 +1,15 @@
import asyncio
import io
import os
import re
import time
import typing
import discord
from rich.console import Console
import time
import re
from dns import asyncresolver
from rich.tree import Tree
import asyncio
from discord.ext import commands
from dns import asyncresolver
from rich.console import Console
from rich.tree import Tree
class NetworkCog(commands.Cog):

View file

@ -1,21 +1,16 @@
import asyncio
import datetime
import io
import logging
import shutil
import os
import tempfile
import time
import zipfile
from urllib.parse import urlparse
from PIL import Image
import discord
from discord.ext import commands
import asyncio
import aiohttp
from pathlib import Path
from PIL import Image
from selenium import webdriver
from selenium.common.exceptions import WebDriverException
from selenium.webdriver.chrome.options import Options as ChromeOptions
from selenium.webdriver.chrome.service import Service as ChromeService
@ -30,174 +25,22 @@ class ScreenshotCog(commands.Cog):
# self.chrome_options.add_argument("--disable-gpu")
self.chrome_options.add_argument("--disable-extensions")
self.chrome_options.add_argument("--incognito")
if os.getuid() == 0:
self.chrome_options.add_argument("--no-sandbox")
prefs = {
# "download.open_pdf_in_system_reader": False,
"download.open_pdf_in_system_reader": False,
# "download.prompt_for_download": True,
# "download.default_directory": "/dev/null",
# "plugins.always_open_pdf_externally": False,
"plugins.always_open_pdf_externally": False,
"download_restrictions": 3,
}
self.chrome_options.add_experimental_option(
"prefs", prefs
)
self.dir = Path(__file__).parent.parent / "chrome"
self.dir.mkdir(mode=0o775, exist_ok=True)
self.chrome_dir = self.dir / "chrome-headless-shell-linux64"
self.chrome_bin = self.chrome_dir / "chrome-headless-shell"
self.chromedriver_dir = self.dir / "chromedriver-linux64"
self.chromedriver_bin = self.chromedriver_dir / "chromedriver"
self.chrome_options.binary_location = str(self.chrome_bin.resolve())
self.log = logging.getLogger("jimmy.cogs.screenshot")
def clear_directories(self):
shutil.rmtree(self.chrome_dir, ignore_errors=True)
shutil.rmtree(self.chromedriver_dir, ignore_errors=True)
self.chrome_dir.mkdir(mode=0o775, exist_ok=True)
self.chromedriver_dir.mkdir(mode=0o775, exist_ok=True)
async def download_latest_chrome(self, current: str = None, *, channel: str = "Stable"):
async with aiohttp.ClientSession(raise_for_status=True) as session:
async with session.get(
"https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions-with-downloads.json",
) as response:
versions = await response.json()
self.log.debug("Got chrome versions: %r", versions)
downloads = versions["channels"][channel]["downloads"]
version = versions["channels"][channel]["version"]
if version == current:
self.log.debug(f"Chrome is up to date ({versions} == {current})")
return
self.log.debug("Downloading chrome...")
chrome_zip_url = filter(lambda x: x["platform"] == "linux64", downloads["chrome-headless-shell"])
if not chrome_zip_url:
self.log.critical("No chrome zip url found for linux64 in %r.", downloads["chrome-headless-shell"])
raise RuntimeError("No chrome zip url found for linux64.")
chrome_zip_url = next(chrome_zip_url)["url"]
self.log.debug("Chrome zip url: %s", chrome_zip_url)
self.clear_directories()
chrome_target = (self.chrome_dir.parent / f"chrome-download-{version}.zip")
chromedriver_target = (self.chromedriver_dir.parent / f"chromedriver-download-{version}.zip")
if chrome_target.exists():
chrome_target.unlink()
if chromedriver_target.exists():
chromedriver_target.unlink()
with chrome_target.open("wb+") as file:
async with session.get(chrome_zip_url) as response:
async for data in response.content.iter_any():
self.log.debug("Read %d bytes from chrome zip.", len(data))
file.write(data)
self.log.debug("Extracting chrome...")
with zipfile.ZipFile(chrome_target) as zip_file:
await asyncio.get_event_loop().run_in_executor(
None,
zip_file.extractall,
self.chrome_dir.parent
)
self.log.debug("Finished extracting chrome.")
self.log.debug("Downloading chromedriver...")
chromedriver_zip_url = filter(lambda x: x["platform"] == "linux64", downloads["chromedriver"])
if not chromedriver_zip_url:
self.log.critical("No chromedriver zip url found for linux64 in %r.", downloads["chromedriver"])
raise RuntimeError("No chromedriver zip url found for linux64.")
chromedriver_zip_url = next(chromedriver_zip_url)["url"]
self.log.debug("Chromedriver zip url: %s", chromedriver_zip_url)
with chromedriver_target.open("wb+") as file:
async with session.get(chromedriver_zip_url) as response:
async for data in response.content.iter_any():
self.log.debug("Read %d bytes from chromedriver zip.", len(data))
file.write(data)
self.log.debug("Extracting chromedriver...")
with zipfile.ZipFile(chromedriver_target) as zip_file:
await asyncio.get_event_loop().run_in_executor(
None,
zip_file.extractall,
self.chromedriver_dir.parent
)
self.log.debug("Finished extracting chromedriver.")
self.log.debug("Making binaries executable.")
await asyncio.get_event_loop().run_in_executor(
None,
self.chrome_bin.chmod,
0o775
)
await asyncio.get_event_loop().run_in_executor(
None,
self.chromedriver_bin.chmod,
0o775
)
self.log.debug("Finished making binaries executable.")
async def get_version(self, full: bool = False) -> str:
proc = await asyncio.create_subprocess_exec(
str(self.chromedriver_bin),
"--version",
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE
)
stdout, stderr = await proc.communicate()
if proc.returncode != 0:
raise RuntimeError(f"Error getting chromedriver version: {stderr.decode()}")
if full:
return stdout.decode().strip()
return stdout.decode().strip().split(" ")[1]
async def is_up_to_date(self, channel: str = "Stable"):
try:
current = await self.get_version(False)
except (RuntimeError, FileNotFoundError):
return False
async with aiohttp.ClientSession(raise_for_status=True) as session:
async with session.get(
"https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions-with-downloads.json",
) as response:
versions = await response.json()
self.log.debug("Got chrome versions: %r", versions)
version = versions["channels"][channel]["version"]
if version == current:
self.log.debug(f"Chrome is up to date ({versions} == {current})")
return True
return False
@commands.command(name="update-chrome")
async def update_chrome(self, ctx: commands.Context, channel: str = "Stable"):
channel = channel.title()
if await self.is_up_to_date(channel):
await ctx.reply("Chrome is already up to date. Updating anyway.")
async with ctx.channel.typing():
try:
await self.download_latest_chrome(channel)
except RuntimeError as e:
return await ctx.reply(f"\N{cross mark} Error downloading chrome: {e}")
chrome_okay = self.chrome_bin.exists() and self.chrome_bin.is_file()
chromedriver_okay = self.chromedriver_bin.exists() and self.chromedriver_bin.is_file()
try:
chromedriver_version = await self.get_version(True)
except RuntimeError as e:
chromedriver_version = str(e)
return await ctx.reply(
f"\N{white heavy check mark} Done.\n"
f"CHANNEL: {channel}\n"
f"CHROME OKAY: {chrome_okay}\n"
f"CHROMEDRIVER OKAY: {chromedriver_okay}\n"
f"CHROMEDRIVER VERSION: {chromedriver_version}"
)
def compress_png(self, input_file: io.BytesIO) -> io.BytesIO:
img = Image.open(input_file)
img = img.convert("RGB")
@ -220,6 +63,7 @@ class ScreenshotCog(commands.Cog):
raise RuntimeError("Couldn't compress image.")
return value
# noinspection PyTypeChecker
@commands.slash_command()
async def screenshot(
self,
@ -242,17 +86,8 @@ class ScreenshotCog(commands.Cog):
parsed = urlparse(url)
await ctx.respond("Initialising...")
if not all(map(lambda x: x.exists() and x.is_file(), (self.chrome_bin, self.chromedriver_bin))):
await ctx.edit(content="Chrome is not installed, downloading. This may take a minute.")
await self.download_latest_chrome()
await ctx.edit(content="Initialising...")
elif not await self.is_up_to_date():
await ctx.edit(content="Updating chrome. This may take a minute.")
await self.download_latest_chrome()
await ctx.edit(content="Initialising...")
start_init = time.time()
service = await asyncio.to_thread(ChromeService, str(self.chromedriver_bin))
service = await asyncio.to_thread(ChromeService)
driver: webdriver.Chrome = await asyncio.to_thread(
webdriver.Chrome,
service=service,

View file

@ -1,17 +1,16 @@
import asyncio
import functools
import logging
import tempfile
import textwrap
import typing
from pathlib import Path
from urllib.parse import urlparse
import discord
import yt_dlp
from urllib.parse import urlparse
from pathlib import Path
import tempfile
from discord.ext import commands
COOKIES_TXT = Path.cwd() / "cookies.txt"

View file

@ -1,2 +1,6 @@
[jimmy]
token = "foo"
token = "token"
debug_guilds = [994710566612500550]
[logging]
level = "DEBUG"

13
main.py
View file

@ -1,14 +1,13 @@
import datetime
import traceback
import toml
import discord
import logging
from pathlib import Path
from rich.logging import RichHandler
import traceback
from logging import FileHandler
from discord.ext import commands
from pathlib import Path
import discord
import toml
from discord.ext import commands
from rich.logging import RichHandler
log = logging.getLogger("jimmy")

View file

@ -1,9 +1,12 @@
wheel>=0.42
setuptools>=69
yt-dlp @ https://github.com/yt-dlp/yt-dlp/archive/master.tar.gz
py-cord==2.4.1
# py-cord==2.4.1
py-cord @ git+https://github.com/Pycord-Development/pycord.git
httpx==0.26
psycopg==3.1.16
toml==0.10.2
pillow==10.2
selenium==4.16
rich==13.7
dnspython==2.4.2