mirror of
https://github.com/nexy7574/LCC-bot.git
synced 2024-09-19 10:03:40 +01:00
Merge remote-tracking branch 'origin/master'
# Conflicts: # .idea/dataSources.local.xml # .idea/misc.xml
This commit is contained in:
commit
660b9fdb84
3 changed files with 86 additions and 61 deletions
2
.idea/.gitignore
vendored
2
.idea/.gitignore
vendored
|
@ -1,3 +1,5 @@
|
||||||
# Default ignored files
|
# Default ignored files
|
||||||
/shelf/
|
/shelf/
|
||||||
/workspace.xml
|
/workspace.xml
|
||||||
|
# GitHub Copilot persisted chat sessions
|
||||||
|
/copilot/chatSessions
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
<module type="PYTHON_MODULE" version="4">
|
<module type="PYTHON_MODULE" version="4">
|
||||||
<component name="NewModuleRootManager">
|
<component name="NewModuleRootManager">
|
||||||
<content url="file://$MODULE_DIR$">
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/.idea/copilot/chatSessions" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="inheritedJdk" />
|
||||||
|
|
143
cogs/other.py
143
cogs/other.py
|
@ -1,55 +1,42 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
import fnmatch
|
|
||||||
import functools
|
|
||||||
import glob
|
import glob
|
||||||
import hashlib
|
import hashlib
|
||||||
import io
|
import io
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import math
|
|
||||||
import os
|
import os
|
||||||
import pathlib
|
import pathlib
|
||||||
import random
|
import random
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
import tempfile
|
import tempfile
|
||||||
import textwrap
|
import textwrap
|
||||||
import traceback
|
|
||||||
import typing
|
import typing
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from io import BytesIO
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from time import sleep, time, time_ns
|
from time import time
|
||||||
from typing import Dict, Literal, Optional, Tuple
|
from typing import Dict, Literal, Tuple
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
import aiofiles
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
|
import config
|
||||||
import discord
|
import discord
|
||||||
import dns.resolver
|
|
||||||
import httpx
|
import httpx
|
||||||
import openai
|
import openai
|
||||||
import psutil
|
import psutil
|
||||||
import pydub
|
import pydub
|
||||||
import pytesseract
|
import pytesseract
|
||||||
import pyttsx3
|
import pyttsx3
|
||||||
from discord import Interaction
|
|
||||||
from discord.ext import commands
|
|
||||||
from dns import asyncresolver
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from rich import print
|
from discord.ext import commands
|
||||||
from rich.tree import Tree
|
|
||||||
from selenium import webdriver
|
from selenium import webdriver
|
||||||
from selenium.common.exceptions import WebDriverException
|
|
||||||
from selenium.webdriver.chrome.options import Options as ChromeOptions
|
from selenium.webdriver.chrome.options import Options as ChromeOptions
|
||||||
from selenium.webdriver.chrome.service import Service as ChromeService
|
from selenium.webdriver.chrome.service import Service as ChromeService
|
||||||
from selenium.webdriver.firefox.options import Options as FirefoxOptions
|
from selenium.webdriver.firefox.options import Options as FirefoxOptions
|
||||||
from selenium.webdriver.firefox.service import Service as FirefoxService
|
from selenium.webdriver.firefox.service import Service as FirefoxService
|
||||||
|
|
||||||
import config
|
from utils import Timer
|
||||||
from utils import Timer, console
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from config import proxy
|
from config import proxy
|
||||||
|
@ -530,21 +517,8 @@ class OtherCog(commands.Cog):
|
||||||
else:
|
else:
|
||||||
return await ctx.respond(result, view=GenerateNewView())
|
return await ctx.respond(result, view=GenerateNewView())
|
||||||
|
|
||||||
@commands.slash_command()
|
async def _ocr_core(self, attachment: discord.Attachment) -> tuple[dict[str, float], str]:
|
||||||
@commands.cooldown(1, 30, commands.BucketType.user)
|
timings: dict[str, float] = {}
|
||||||
@commands.max_concurrency(1, commands.BucketType.user)
|
|
||||||
async def ocr(
|
|
||||||
self,
|
|
||||||
ctx: discord.ApplicationContext,
|
|
||||||
attachment: discord.Option(
|
|
||||||
discord.SlashCommandOptionType.attachment,
|
|
||||||
description="Image to perform OCR on",
|
|
||||||
),
|
|
||||||
):
|
|
||||||
"""OCRs an image"""
|
|
||||||
await ctx.defer()
|
|
||||||
timings: Dict[str, float] = {}
|
|
||||||
attachment: discord.Attachment
|
|
||||||
with Timer() as _t:
|
with Timer() as _t:
|
||||||
data = await attachment.read()
|
data = await attachment.read()
|
||||||
file = io.BytesIO(data)
|
file = io.BytesIO(data)
|
||||||
|
@ -558,45 +532,92 @@ class OtherCog(commands.Cog):
|
||||||
text = await self.bot.loop.run_in_executor(None, pytesseract.image_to_string, img)
|
text = await self.bot.loop.run_in_executor(None, pytesseract.image_to_string, img)
|
||||||
timings["Perform OCR"] = _t.total
|
timings["Perform OCR"] = _t.total
|
||||||
except pytesseract.TesseractError as e:
|
except pytesseract.TesseractError as e:
|
||||||
return await ctx.respond(f"Failed to perform OCR: `{e}`")
|
raise RuntimeError(f"Failed to perform OCR: `{e}`")
|
||||||
|
|
||||||
if len(text) > 4096:
|
if len(text) >= 1744:
|
||||||
with Timer() as _t:
|
with Timer() as _t:
|
||||||
try:
|
try:
|
||||||
response = await self.http.put(
|
file.seek(0)
|
||||||
"https://api.mystb.in/paste",
|
response = await self.http.post(
|
||||||
json={
|
"https://paste.nexy7574.co.uk/upload",
|
||||||
"files": [{"filename": "ocr.txt", "content": text}],
|
data={
|
||||||
|
"expiration": "1week",
|
||||||
|
"burn_after": "0",
|
||||||
|
"syntax_highlight": "none",
|
||||||
|
"privacy": "unlisted",
|
||||||
|
"content": text
|
||||||
},
|
},
|
||||||
|
files={
|
||||||
|
"file": (attachment.filename, file, attachment.content_type)
|
||||||
|
},
|
||||||
|
follow_redirects=False
|
||||||
)
|
)
|
||||||
response.raise_for_status()
|
if response.status_code not in range(200, 400):
|
||||||
except httpx.HTTPError:
|
response.raise_for_status()
|
||||||
return await ctx.respond("OCR content too large to post.")
|
except httpx.HTTPError as e:
|
||||||
|
raise RuntimeError(f"Failed to upload OCR content: `{e}`")
|
||||||
else:
|
else:
|
||||||
data = response.json()
|
text = "View on [paste.nexy7574.co.uk](%s)" % response.next_request.url
|
||||||
with Timer(timings, "Respond (URL)"):
|
timings["Upload text to pastebin"] = _t.total
|
||||||
embed = discord.Embed(
|
return timings, text
|
||||||
description="View on [mystb.in](%s)" % ("https://mystb.in/" + data["id"]),
|
|
||||||
colour=discord.Colour.dark_theme(),
|
@commands.slash_command()
|
||||||
)
|
@commands.cooldown(1, 30, commands.BucketType.user)
|
||||||
await ctx.respond(embed=embed)
|
@commands.max_concurrency(1, commands.BucketType.user)
|
||||||
timings["Upload text to mystbin"] = _t.total
|
async def ocr(
|
||||||
elif len(text) <= 1500:
|
self,
|
||||||
with Timer() as _t:
|
ctx: discord.ApplicationContext,
|
||||||
await ctx.respond(embed=discord.Embed(description=text))
|
attachment: discord.Option(
|
||||||
timings["Respond (Text)"] = _t.total
|
discord.SlashCommandOptionType.attachment,
|
||||||
else:
|
description="Image to perform OCR on",
|
||||||
with Timer() as _t:
|
),
|
||||||
out_file = io.BytesIO(text.encode("utf-8", "replace"))
|
):
|
||||||
await ctx.respond(file=discord.File(out_file, filename="ocr.txt"))
|
"""OCRs an image"""
|
||||||
timings["Respond (File)"] = _t.total
|
await ctx.defer()
|
||||||
|
attachment: discord.Attachment
|
||||||
|
|
||||||
|
timings, text = await self._ocr_core(attachment)
|
||||||
|
embed = discord.Embed(
|
||||||
|
description=text,
|
||||||
|
colour=discord.Colour.blurple()
|
||||||
|
)
|
||||||
|
embed.set_image(url=attachment.url)
|
||||||
|
with Timer() as _t:
|
||||||
|
await ctx.respond(
|
||||||
|
embed=embed
|
||||||
|
)
|
||||||
|
timings["Respond (Text)"] = _t.total
|
||||||
|
|
||||||
if timings:
|
if timings:
|
||||||
text = "Timings:\n" + "\n".join("{}: {:.2f}s".format(k.title(), v) for k, v in timings.items())
|
text = "Timings:\n" + "\n".join("{}: {:.2f}s".format(k.title(), v) for k, v in timings.items())
|
||||||
await ctx.edit(
|
await ctx.edit(
|
||||||
content=text,
|
content=text
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@commands.message_command(name="Run OCR")
|
||||||
|
async def message_ocr(self, ctx: discord.ApplicationContext, message: discord.Message):
|
||||||
|
await ctx.defer()
|
||||||
|
|
||||||
|
embeds = []
|
||||||
|
for attachment in message.attachments:
|
||||||
|
if attachment.content_type.startswith("image/"):
|
||||||
|
timings, text = await self._ocr_core(attachment)
|
||||||
|
embed = discord.Embed(
|
||||||
|
title="OCR for " + attachment.filename,
|
||||||
|
description=text,
|
||||||
|
colour=discord.Colour.blurple(),
|
||||||
|
url=message.jump_url
|
||||||
|
)
|
||||||
|
embed.set_image(url=attachment.url)
|
||||||
|
embeds.append(embed)
|
||||||
|
if len(embeds) == 25:
|
||||||
|
break
|
||||||
|
|
||||||
|
if not embeds:
|
||||||
|
return await ctx.respond(":x: No images found in message.", delete_after=30)
|
||||||
|
else:
|
||||||
|
return await ctx.respond(embeds=embeds)
|
||||||
|
|
||||||
@commands.message_command(name="Convert Image to GIF")
|
@commands.message_command(name="Convert Image to GIF")
|
||||||
async def convert_image_to_gif(self, ctx: discord.ApplicationContext, message: discord.Message):
|
async def convert_image_to_gif(self, ctx: discord.ApplicationContext, message: discord.Message):
|
||||||
await ctx.defer()
|
await ctx.defer()
|
||||||
|
|
Loading…
Reference in a new issue