The world's most clever kitty cat

Merge pull request #5 from loco-choco/main

Adds read text from image via ocr (admin only)

authored by bwc9876.dev and committed by

GitHub 91aadb17 b57b77ac

+112 -30
+24 -24
nix/devShell.nix
··· 1 - { pkgs 2 - , lib 3 - , outputs 4 - , ... 5 - }: 1 + { pkgs, lib, outputs, ... }: 6 2 let 7 - editableOverlay = outputs.lib.workspace.mkEditablePyprojectOverlay { 8 - root = "$REPO_ROOT"; 9 - }; 10 - editablePythonSet = (outputs.lib.pythonSetForPkgs pkgs).overrideScope (lib.composeManyExtensions [ 11 - editableOverlay 12 - (final: prev: { 13 - bingus = prev.bingus.overrideAttrs (old: { 14 - nativeBuildInputs = 15 - old.nativeBuildInputs 16 - ++ final.resolveBuildSystem { 17 - editables = [ ]; 18 - }; 19 - }); 20 - }) 21 - ]); 22 - virtualenv = editablePythonSet.mkVirtualEnv "bingus-dev-env" outputs.lib.workspace.deps.all; 23 - in 24 - pkgs.mkShell { 25 - packages = with pkgs; [ uv ruff virtualenv python312Packages.hatchling alejandra ]; 3 + editableOverlay = 4 + outputs.lib.workspace.mkEditablePyprojectOverlay { root = "$REPO_ROOT"; }; 5 + editablePythonSet = (outputs.lib.pythonSetForPkgs pkgs).overrideScope 6 + (lib.composeManyExtensions [ 7 + editableOverlay 8 + (final: prev: { 9 + bingus = prev.bingus.overrideAttrs (old: { 10 + nativeBuildInputs = old.nativeBuildInputs 11 + ++ final.resolveBuildSystem { editables = [ ]; }; 12 + }); 13 + }) 14 + ]); 15 + virtualenv = editablePythonSet.mkVirtualEnv "bingus-dev-env" 16 + outputs.lib.workspace.deps.all; 17 + in pkgs.mkShell { 18 + packages = with pkgs; [ 19 + uv 20 + ruff 21 + virtualenv 22 + python312Packages.hatchling 23 + alejandra 24 + tesseract 25 + ]; 26 26 env = { 27 27 UV_NO_SYNC = "1"; 28 28 UV_PYTHON = "${virtualenv}/bin/python";
+2
pyproject.toml
··· 12 12 "msgpack>=1.1.0", 13 13 "py-cord>=2.6.1", 14 14 "python-dotenv>=1.0.1", 15 + "pytesseract>=0.3.13", 16 + "pillow>=11.1.0" 15 17 ] 16 18 17 19 [project.scripts]
+21 -5
src/bingus/cogs/markov.py
··· 2 2 import os 3 3 import io 4 4 import discord 5 + import pytesseract 6 + import PIL 5 7 from discord.ext import commands 6 8 from discord.message import Message 7 9 from pathlib import Path ··· 96 98 97 99 @require_owner 98 100 @commands.slash_command() 101 + async def ocr( 102 + self, ctx: discord.ApplicationContext, file: discord.Option(discord.Attachment) 103 + ): 104 + raw = await file.read() 105 + try: 106 + image = PIL.Image.open(io.BytesIO(raw)) 107 + text = pytesseract.image_to_string(image) 108 + self.markov.learn(text) 109 + await ctx.respond("> Bingus learned something from image!", ephemeral=True) 110 + await self.update_words() 111 + except PIL.UnidentifiedImageError: 112 + await ctx.respond("> Bingus only understands image files!", ephemeral=True) 113 + 114 + @require_owner 115 + @commands.slash_command() 99 116 async def study( 100 117 self, ctx: discord.ApplicationContext, file: discord.Option(discord.Attachment) 101 118 ): ··· 112 129 113 130 @require_owner 114 131 @commands.slash_command() 115 - async def forget( 116 - self, ctx: discord.ApplicationContext): 117 - self.markov.forget() 118 - await ctx.respond("> Bingus forgot everything!", ephemeral=True) 119 - await self.update_words() 132 + async def forget(self, ctx: discord.ApplicationContext): 133 + self.markov.forget() 134 + await ctx.respond("> Bingus forgot everything!", ephemeral=True) 135 + await self.update_words() 120 136 121 137 @commands.Cog.listener() 122 138 async def on_ready(self):
+1 -1
src/bingus/lib/markov.py
··· 131 131 self._learn_from_tokens(tokens) 132 132 133 133 def forget(self): 134 - self.edges = {} 134 + self.edges = {} 135 135 136 136 def _pick_next(self, current_token: Token, allow_end: bool) -> Token: 137 137 transitions = self.edges.get(current_token)
+64
uv.lock
··· 88 88 dependencies = [ 89 89 { name = "brotli" }, 90 90 { name = "msgpack" }, 91 + { name = "pillow" }, 91 92 { name = "py-cord" }, 93 + { name = "pytesseract" }, 92 94 { name = "python-dotenv" }, 93 95 ] 94 96 ··· 96 98 requires-dist = [ 97 99 { name = "brotli", specifier = ">=1.1.0" }, 98 100 { name = "msgpack", specifier = ">=1.1.0" }, 101 + { name = "pillow", specifier = ">=11.1.0" }, 99 102 { name = "py-cord", specifier = ">=2.6.1" }, 103 + { name = "pytesseract", specifier = ">=0.3.13" }, 100 104 { name = "python-dotenv", specifier = ">=1.0.1" }, 101 105 ] 102 106 ··· 259 263 ] 260 264 261 265 [[package]] 266 + name = "packaging" 267 + version = "24.2" 268 + source = { registry = "https://pypi.org/simple" } 269 + sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950 } 270 + wheels = [ 271 + { url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451 }, 272 + ] 273 + 274 + [[package]] 275 + name = "pillow" 276 + version = "11.1.0" 277 + source = { registry = "https://pypi.org/simple" } 278 + sdist = { url = "https://files.pythonhosted.org/packages/f3/af/c097e544e7bd278333db77933e535098c259609c4eb3b85381109602fb5b/pillow-11.1.0.tar.gz", hash = "sha256:368da70808b36d73b4b390a8ffac11069f8a5c85f29eff1f1b01bcf3ef5b2a20", size = 46742715 } 279 + wheels = [ 280 + { url = "https://files.pythonhosted.org/packages/95/20/9ce6ed62c91c073fcaa23d216e68289e19d95fb8188b9fb7a63d36771db8/pillow-11.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2062ffb1d36544d42fcaa277b069c88b01bb7298f4efa06731a7fd6cc290b81a", size = 3226818 }, 281 + { url = "https://files.pythonhosted.org/packages/b9/d8/f6004d98579a2596c098d1e30d10b248798cceff82d2b77aa914875bfea1/pillow-11.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a85b653980faad27e88b141348707ceeef8a1186f75ecc600c395dcac19f385b", size = 3101662 }, 282 + { url = "https://files.pythonhosted.org/packages/08/d9/892e705f90051c7a2574d9f24579c9e100c828700d78a63239676f960b74/pillow-11.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9409c080586d1f683df3f184f20e36fb647f2e0bc3988094d4fd8c9f4eb1b3b3", size = 4329317 }, 283 + { url = "https://files.pythonhosted.org/packages/8c/aa/7f29711f26680eab0bcd3ecdd6d23ed6bce180d82e3f6380fb7ae35fcf3b/pillow-11.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7fdadc077553621911f27ce206ffcbec7d3f8d7b50e0da39f10997e8e2bb7f6a", size = 4412999 }, 284 + { url = "https://files.pythonhosted.org/packages/c8/c4/8f0fe3b9e0f7196f6d0bbb151f9fba323d72a41da068610c4c960b16632a/pillow-11.1.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:93a18841d09bcdd774dcdc308e4537e1f867b3dec059c131fde0327899734aa1", size = 4368819 }, 285 + { url = "https://files.pythonhosted.org/packages/38/0d/84200ed6a871ce386ddc82904bfadc0c6b28b0c0ec78176871a4679e40b3/pillow-11.1.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:9aa9aeddeed452b2f616ff5507459e7bab436916ccb10961c4a382cd3e03f47f", size = 4496081 }, 286 + { url = "https://files.pythonhosted.org/packages/84/9c/9bcd66f714d7e25b64118e3952d52841a4babc6d97b6d28e2261c52045d4/pillow-11.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3cdcdb0b896e981678eee140d882b70092dac83ac1cdf6b3a60e2216a73f2b91", size = 4296513 }, 287 + { url = "https://files.pythonhosted.org/packages/db/61/ada2a226e22da011b45f7104c95ebda1b63dcbb0c378ad0f7c2a710f8fd2/pillow-11.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:36ba10b9cb413e7c7dfa3e189aba252deee0602c86c309799da5a74009ac7a1c", size = 4431298 }, 288 + { url = "https://files.pythonhosted.org/packages/e7/c4/fc6e86750523f367923522014b821c11ebc5ad402e659d8c9d09b3c9d70c/pillow-11.1.0-cp312-cp312-win32.whl", hash = "sha256:cfd5cd998c2e36a862d0e27b2df63237e67273f2fc78f47445b14e73a810e7e6", size = 2291630 }, 289 + { url = "https://files.pythonhosted.org/packages/08/5c/2104299949b9d504baf3f4d35f73dbd14ef31bbd1ddc2c1b66a5b7dfda44/pillow-11.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:a697cd8ba0383bba3d2d3ada02b34ed268cb548b369943cd349007730c92bddf", size = 2626369 }, 290 + { url = "https://files.pythonhosted.org/packages/37/f3/9b18362206b244167c958984b57c7f70a0289bfb59a530dd8af5f699b910/pillow-11.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:4dd43a78897793f60766563969442020e90eb7847463eca901e41ba186a7d4a5", size = 2375240 }, 291 + { url = "https://files.pythonhosted.org/packages/b3/31/9ca79cafdce364fd5c980cd3416c20ce1bebd235b470d262f9d24d810184/pillow-11.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ae98e14432d458fc3de11a77ccb3ae65ddce70f730e7c76140653048c71bfcbc", size = 3226640 }, 292 + { url = "https://files.pythonhosted.org/packages/ac/0f/ff07ad45a1f172a497aa393b13a9d81a32e1477ef0e869d030e3c1532521/pillow-11.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cc1331b6d5a6e144aeb5e626f4375f5b7ae9934ba620c0ac6b3e43d5e683a0f0", size = 3101437 }, 293 + { url = "https://files.pythonhosted.org/packages/08/2f/9906fca87a68d29ec4530be1f893149e0cb64a86d1f9f70a7cfcdfe8ae44/pillow-11.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:758e9d4ef15d3560214cddbc97b8ef3ef86ce04d62ddac17ad39ba87e89bd3b1", size = 4326605 }, 294 + { url = "https://files.pythonhosted.org/packages/b0/0f/f3547ee15b145bc5c8b336401b2d4c9d9da67da9dcb572d7c0d4103d2c69/pillow-11.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b523466b1a31d0dcef7c5be1f20b942919b62fd6e9a9be199d035509cbefc0ec", size = 4411173 }, 295 + { url = "https://files.pythonhosted.org/packages/b1/df/bf8176aa5db515c5de584c5e00df9bab0713548fd780c82a86cba2c2fedb/pillow-11.1.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:9044b5e4f7083f209c4e35aa5dd54b1dd5b112b108648f5c902ad586d4f945c5", size = 4369145 }, 296 + { url = "https://files.pythonhosted.org/packages/de/7c/7433122d1cfadc740f577cb55526fdc39129a648ac65ce64db2eb7209277/pillow-11.1.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:3764d53e09cdedd91bee65c2527815d315c6b90d7b8b79759cc48d7bf5d4f114", size = 4496340 }, 297 + { url = "https://files.pythonhosted.org/packages/25/46/dd94b93ca6bd555588835f2504bd90c00d5438fe131cf01cfa0c5131a19d/pillow-11.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:31eba6bbdd27dde97b0174ddf0297d7a9c3a507a8a1480e1e60ef914fe23d352", size = 4296906 }, 298 + { url = "https://files.pythonhosted.org/packages/a8/28/2f9d32014dfc7753e586db9add35b8a41b7a3b46540e965cb6d6bc607bd2/pillow-11.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b5d658fbd9f0d6eea113aea286b21d3cd4d3fd978157cbf2447a6035916506d3", size = 4431759 }, 299 + { url = "https://files.pythonhosted.org/packages/33/48/19c2cbe7403870fbe8b7737d19eb013f46299cdfe4501573367f6396c775/pillow-11.1.0-cp313-cp313-win32.whl", hash = "sha256:f86d3a7a9af5d826744fabf4afd15b9dfef44fe69a98541f666f66fbb8d3fef9", size = 2291657 }, 300 + { url = "https://files.pythonhosted.org/packages/3b/ad/285c556747d34c399f332ba7c1a595ba245796ef3e22eae190f5364bb62b/pillow-11.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:593c5fd6be85da83656b93ffcccc2312d2d149d251e98588b14fbc288fd8909c", size = 2626304 }, 301 + { url = "https://files.pythonhosted.org/packages/e5/7b/ef35a71163bf36db06e9c8729608f78dedf032fc8313d19bd4be5c2588f3/pillow-11.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:11633d58b6ee5733bde153a8dafd25e505ea3d32e261accd388827ee987baf65", size = 2375117 }, 302 + { url = "https://files.pythonhosted.org/packages/79/30/77f54228401e84d6791354888549b45824ab0ffde659bafa67956303a09f/pillow-11.1.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:70ca5ef3b3b1c4a0812b5c63c57c23b63e53bc38e758b37a951e5bc466449861", size = 3230060 }, 303 + { url = "https://files.pythonhosted.org/packages/ce/b1/56723b74b07dd64c1010fee011951ea9c35a43d8020acd03111f14298225/pillow-11.1.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:8000376f139d4d38d6851eb149b321a52bb8893a88dae8ee7d95840431977081", size = 3106192 }, 304 + { url = "https://files.pythonhosted.org/packages/e1/cd/7bf7180e08f80a4dcc6b4c3a0aa9e0b0ae57168562726a05dc8aa8fa66b0/pillow-11.1.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ee85f0696a17dd28fbcfceb59f9510aa71934b483d1f5601d1030c3c8304f3c", size = 4446805 }, 305 + { url = "https://files.pythonhosted.org/packages/97/42/87c856ea30c8ed97e8efbe672b58c8304dee0573f8c7cab62ae9e31db6ae/pillow-11.1.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:dd0e081319328928531df7a0e63621caf67652c8464303fd102141b785ef9547", size = 4530623 }, 306 + { url = "https://files.pythonhosted.org/packages/ff/41/026879e90c84a88e33fb00cc6bd915ac2743c67e87a18f80270dfe3c2041/pillow-11.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e63e4e5081de46517099dc30abe418122f54531a6ae2ebc8680bcd7096860eab", size = 4465191 }, 307 + { url = "https://files.pythonhosted.org/packages/e5/fb/a7960e838bc5df57a2ce23183bfd2290d97c33028b96bde332a9057834d3/pillow-11.1.0-cp313-cp313t-win32.whl", hash = "sha256:dda60aa465b861324e65a78c9f5cf0f4bc713e4309f83bc387be158b077963d9", size = 2295494 }, 308 + { url = "https://files.pythonhosted.org/packages/d7/6c/6ec83ee2f6f0fda8d4cf89045c6be4b0373ebfc363ba8538f8c999f63fcd/pillow-11.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ad5db5781c774ab9a9b2c4302bbf0c1014960a0a7be63278d13ae6fdf88126fe", size = 2631595 }, 309 + { url = "https://files.pythonhosted.org/packages/cf/6c/41c21c6c8af92b9fea313aa47c75de49e2f9a467964ee33eb0135d47eb64/pillow-11.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:67cd427c68926108778a9005f2a04adbd5e67c442ed21d95389fe1d595458756", size = 2377651 }, 310 + ] 311 + 312 + [[package]] 262 313 name = "propcache" 263 314 version = "0.2.1" 264 315 source = { registry = "https://pypi.org/simple" } ··· 309 360 sdist = { url = "https://files.pythonhosted.org/packages/27/c7/c539d69d5cfa1ea5891d596212f73d619e40c7fc9f02ae906f4147993b94/py_cord-2.6.1.tar.gz", hash = "sha256:36064f225f2c7bbddfe542d5ed581f2a5744f618e039093cf7cd2659a58bc79b", size = 965087 } 310 361 wheels = [ 311 362 { url = "https://files.pythonhosted.org/packages/e7/90/2690ded84e34b15ca2619932a358c1b7dc6d28fe845dfbd01929fc33c9da/py_cord-2.6.1-py3-none-any.whl", hash = "sha256:e3d3b528c5e37b0e0825f5b884cbb9267860976c1e4878e28b55da8fd3af834b", size = 1089154 }, 363 + ] 364 + 365 + [[package]] 366 + name = "pytesseract" 367 + version = "0.3.13" 368 + source = { registry = "https://pypi.org/simple" } 369 + dependencies = [ 370 + { name = "packaging" }, 371 + { name = "pillow" }, 372 + ] 373 + sdist = { url = "https://files.pythonhosted.org/packages/9f/a6/7d679b83c285974a7cb94d739b461fa7e7a9b17a3abfd7bf6cbc5c2394b0/pytesseract-0.3.13.tar.gz", hash = "sha256:4bf5f880c99406f52a3cfc2633e42d9dc67615e69d8a509d74867d3baddb5db9", size = 17689 } 374 + wheels = [ 375 + { url = "https://files.pythonhosted.org/packages/7a/33/8312d7ce74670c9d39a532b2c246a853861120486be9443eebf048043637/pytesseract-0.3.13-py3-none-any.whl", hash = "sha256:7a99c6c2ac598360693d83a416e36e0b33a67638bb9d77fdcac094a3589d4b34", size = 14705 }, 312 376 ] 313 377 314 378 [[package]]