The world's most clever kitty cat
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Update README, NixOS Module

Ben C 77e4635e cad5a22e

+67 -102
+18 -88
README.md
··· 2 2 3 3 A very clever kitty 4 4 5 - Current features: 6 - 7 - - [Markov chain](https://en.wikipedia.org/wiki/Markov_chain) for a "smart" 8 - chatbot 9 - 10 - ## Pre-reqs 11 - 12 - - Python 3.12 13 - - UV 14 - 15 - ## Environment Setup 16 - 17 - `uv sync` 18 - 19 - ### .env 20 - 21 - Minimal needed is an env var called `TOKEN` that contains the bot's token. 22 - 23 - ## Cog Docs 24 - 25 - ### [Markov](src/bingus/cogs/markov.py) 26 - 27 - A markov chain is an incredibly simple model where it decides the next token 28 - based on previous knowledge of what tokens the current token has been proceeded 29 - by. 30 - 31 - #### Markov Commands 32 - 33 - > **\*** = Requires being bot owner 34 - 35 - - `/markov`: Make bingus try and reply to a prompt passed, use this to bypass 36 - the 80% change that bingus usually has to reply 37 - - `/scan_history`*: Scan the history of the current channel and add it to the 38 - chain. Since Bingus only learns from*new\* messages while he's active, you may 39 - need to do this when restarting him. This command can take a while depending 40 - on the number of messages. 41 - - `/dump_chain`\*: Dumps the entire underlying markov chain as a JSON file and 42 - sends it 43 - - `/load_chain`\*: Loads a markov chain JSON (as generated by `/dump_chain`) 44 - additively 45 - - `/weights`: Dump the weights of the specified token to other tokens 46 - 47 - #### Markov Config 48 - 49 - - `REPLY_CHANNELS`: A _comma-delimited_ list of channel IDs that the bot should 50 - have have a chance to reply to messages in. The bot still learns from all 51 - channels in realtime, but these channels it'll have an 80% of replying to any 52 - message 53 - 54 - - `BRAIN_FILE`: Path to file where the chain will be persisted. This file will 55 - automatically be created if it doesn't exist already. The file itself is 56 - msgpack compressed with brotli, so it's recommended to give it a `msgpackz` 57 - extension. By default it will be set to `$PWD/brain.msgpackz` 5 + Simple markov chain-based auto replies to user messages. 58 6 59 - ## Adding Cogs 7 + ## Installation 60 8 61 - To start, you can run `poetry run add_cog`. 9 + Use the NixOS module in this flake or build/set it up yourself. Just need Rust. 62 10 63 - Follow the steps and you'll get a new cog in `src/bingus/cogs`. Here is where 64 - you can add commands, event listeners, etc. 11 + ## Configuration 65 12 66 - See the file generated for some simple examples, review the 67 - [PyCord docs](https://guide.pycord.dev/introduction) for more help and 68 - information. 13 + ### `TOKEN_FILE` 69 14 70 - ### Utilities 15 + Path to the file containing the bot's token. 71 16 72 - #### Requiring Owner 17 + ### `BRAIN_FILE` 73 18 74 - To require the calling user to be a bot owner for slash commands, you can use 75 - [permissions.require_owner](src/bingus/lib/permissions.py). Simply put this as a 76 - decorator **above** the slash command one like so: 19 + Path to the file Bingus will save state in. The file will be created if not present. This will be a brotli-compressed MsgPack file. 77 20 78 - ```py 79 - from ..lib.permissions import require_owner 21 + ### `REPLY_CHANNELS` 80 22 81 - class MyCog(discord.commands.Cog): 82 - @require_owner 83 - @commands.slash_command() 84 - async def hello_owner(self, ctx: discord.ApplicationContext): 85 - await ctx.respond("Hello Owner!") 86 - ``` 23 + Comma-delimited list of channel IDs that Bingus should auto reply in. 87 24 88 - This will print an ephemeral error message to all non-owner users and "Hello 89 - Owner!" otherwise. 90 - 91 - ### Best Practices 92 - 93 - Generally you'll want to make all state, config, etc. locallized to your cog 94 - file. That way we can easily disable it if needed and nothing will break. 95 - 96 - #### Cog Config 25 + Bingus will learn from all channels he has access to but will only auto-reply in these ones. 97 26 98 - For simplicity we'll just use env vars for config. 27 + ## Commands 99 28 100 - Try to documents these options within this README file under the 101 - [The individual cogs docs](#cog-docs). Create a third-level heading with your 102 - cog's name, and a link to its source code. 29 + Commands with `*` require you to be the owner of the bot. Create a team in the Discord 30 + dev portal to make multiple people owner. 103 31 104 - #### Formatting 32 + - `/markov`: For a reply from Bingus in the current channel 33 + - `/weights`: View the weights for a specific token 34 + - `/dump_chain`: Dump Bingus' "brain", his entire database of known words and relations 35 + - `/load_chain`: Additively load a brain file into Bingus 105 36 106 - Try to run `poetry run format` every-so-often to format your code.
+49 -14
nix/nixosModule.nix
··· 29 29 30 30 config = lib.mkIf cfg.enable { 31 31 systemd.services.bingus = let 32 - replyChannelsStr = lib.strings.concatStrings (lib.strings.intersperse "," (builtins.map builtins.toString cfg.replyChannels)); 32 + replyChannelsStr = lib.strings.concatStrings ( 33 + lib.strings.intersperse "," (builtins.map builtins.toString cfg.replyChannels) 34 + ); 33 35 in { 34 36 wantedBy = ["multi-user.target"]; 35 - after = ["network.target"]; 36 - 37 - environment.REPLY_CHANNELS = replyChannelsStr; 37 + after = [ 38 + "network-online.target" 39 + ]; 40 + wants = [ 41 + "network-online.target" 42 + ]; 38 43 39 - script = '' 40 - export TOKEN=$(cat "$CREDENTIALS_DIRECTORY/BINGUS_BOT_TOKEN") 41 - export BRAIN_FILE=$STATE_DIRECTORY/brain.msgpackz 42 - ${pkgs.bingus}/bin/bingus 43 - ''; 44 + environment = { 45 + REPLY_CHANNELS = replyChannelsStr; 46 + TOKEN_FILE = "%d/token"; 47 + BRAIN_FILE = "brain.msgpackz"; 48 + }; 44 49 45 50 serviceConfig = { 51 + ExecStart = lib.getExe pkgs.bingus; 46 52 Restart = "always"; 47 - RestartSec = "5s"; 48 - User = "bingus-bot"; 49 - Group = "bingus-bot"; 50 53 StateDirectory = "bingus"; 51 - DynamicUser = true; 52 - LoadCredential = "BINGUS_BOT_TOKEN:${cfg.tokenFile}"; 54 + StateDirectoryMode = "0755"; 55 + LoadCredential = "token:${cfg.tokenFile}"; 56 + 57 + # Hardening 58 + RemoveIPC = true; 59 + CapabilityBoundingSet = ["CAP_NET_BIND_SERVICE"]; 60 + NoNewPrivileges = true; 61 + PrivateDevices = true; 62 + ProtectClock = true; 63 + ProtectKernelLogs = true; 64 + ProtectControlGroups = true; 65 + ProtectKernelModules = true; 66 + PrivateMounts = true; 67 + SystemCallArchitectures = ["native"]; 68 + MemoryDenyWriteExecute = true; 69 + RestrictNamespaces = true; 70 + RestrictSUIDSGID = true; 71 + ProtectHostname = true; 72 + LockPersonality = true; 73 + ProtectKernelTunables = true; 74 + RestrictAddressFamilies = [ 75 + "AF_UNIX" 76 + "AF_INET" 77 + "AF_INET6" 78 + ]; 79 + RestrictRealtime = true; 80 + DeviceAllow = [""]; 81 + ProtectSystem = "strict"; 82 + ProtectProc = "invisible"; 83 + ProcSubset = "pid"; 84 + ProtectHome = true; 85 + PrivateUsers = true; 86 + PrivateTmp = true; 87 + UMask = "0077"; 53 88 }; 54 89 }; 55 90 };