{"id":14109603,"url":"https://github.com/pragma-/pbot","last_synced_at":"2025-04-07T05:16:41.385Z","repository":{"id":25150990,"uuid":"28573480","full_name":"pragma-/pbot","owner":"pragma-","description":"A pragmatic Perl IRCv3 bot","archived":false,"fork":false,"pushed_at":"2024-12-14T23:12:22.000Z","size":78078,"stargazers_count":64,"open_issues_count":1,"forks_count":21,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-03-31T04:07:12.377Z","etag":null,"topics":["applets","dockerfile","extensible","irc","irc-bot","ircv3","perl5","plugins","sandboxed","sasl","scriptable","vagrantfile","virtual-machine"],"latest_commit_sha":null,"homepage":"","language":"Perl","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pragma-.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-12-28T22:53:31.000Z","updated_at":"2024-12-14T23:12:26.000Z","dependencies_parsed_at":"2023-02-14T01:16:00.041Z","dependency_job_id":"2dad7b86-ab9e-442c-8af6-7a0671154dc4","html_url":"https://github.com/pragma-/pbot","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pragma-%2Fpbot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pragma-%2Fpbot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pragma-%2Fpbot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pragma-%2Fpbot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pragma-","download_url":"https://codeload.github.com/pragma-/pbot/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247595335,"owners_count":20963943,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["applets","dockerfile","extensible","irc","irc-bot","ircv3","perl5","plugins","sandboxed","sasl","scriptable","vagrantfile","virtual-machine"],"created_at":"2024-08-14T10:02:24.182Z","updated_at":"2025-04-07T05:16:41.366Z","avatar_url":"https://github.com/pragma-.png","language":"Perl","readme":"# PBot\nPBot is a pragmatic IRCv3 Bot written in Perl\n\n\u003c!-- md-toc-begin --\u003e\n  * [Installation / Quick Start](#installation--quick-start)\n  * [Features](#features)\n    * [IRCv3 capable](#ircv3-capable)\n    * [Powerful command interpreter](#powerful-command-interpreter)\n      * [Piping](#piping)\n      * [Substitution](#substitution)\n      * [Variables](#variables)\n      * [Selectors](#selectors)\n      * [Inline invocation](#inline-invocation)\n      * [Chaining](#chaining)\n      * [Background processing](#background-processing)\n    * [Output customization](#output-customization)\n      * [Newlines in messages](#newlines-in-messages)\n      * [Truncating long messages](#truncating-long-messages)\n    * [Extensible](#extensible)\n      * [Factoids](#factoids)\n      * [Code factoids](#code-factoids)\n      * [Plugins](#plugins)\n      * [Applets](#applets)\n      * [Functions](#functions)\n      * [Scripting interface](#scripting-interface)\n    * [Virtual machine to safely execute user-submitted code](#virtual-machine-to-safely-execute-user-submitted-code)\n    * [Powerful user management](#powerful-user-management)\n    * [Useful IRC quality-of-life improvements](#useful-irc-quality-of-life-improvements)\n    * [Channel management and protection](#channel-management-and-protection)\n    * [Easy configuration](#easy-configuration)\n    * [Live reloading of core modules or data files](#live-reloading-of-core-modules-or-data-files)\n  * [Documentation](#documentation)\n  * [Frequently Asked Questions](#frequently-asked-questions)\n  * [Support](#support)\n  * [License](#license)\n\u003c!-- md-toc-end --\u003e\n\n## Installation / Quick Start\nTo get up-and-running quickly, check out the [Quick Start guide](doc/QuickStart.md).\n\n## Features\n\n### IRCv3 capable\nPBot supports several features of the IRCv3 specification.\n\n* client capability negotiation\n* SASL authentication\n* account-tag, account-notify, extended-join, message-tags, and more.\n\n### Powerful command interpreter\nPBot has a powerful command interpreter with useful functionality, and tons of\nbuilt-in commands.\n\nFor more information, see the [Commands documentation.](doc/Commands.md)\n\n#### Piping\nYou can pipe output from one command as input into another command, indefinitely.\n\n    \u003cpragma-\u003e !echo hello world | {sed s/world/everybody/} | {uc}\n       \u003cPBot\u003e HELLO EVERYBODY\n\n[Learn more.](doc/Commands.md#piping)\n\n#### Substitution\nYou can insert the output from another command at any point within a command. This\nsubstitutes the command with its output at the point where the command was used.\n\n    \u003cpragma-\u003e !echo This is \u0026{echo a demonstration} of command substitution\n       \u003cPBot\u003e This is a demonstration of command substitution\n\nFor example, suppose you want to make a Google Image Search command. The naive\nway would be to simply do:\n\n    \u003cpragma-\u003e !factadd img /call echo https://google.com/search?tbm=isch\u0026q=$args\n\nUnfortuately this would not support queries containing spaces or certain symbols. But\nnever fear! We can use command substitution and the `uri_escape` function from the\n`func` command.\n\nNote that you must escape the command substitution to insert it literally into the\nfactoid otherwise it will be expanded first.\n\n    \u003cpragma-\u003e !factadd img /call echo https://google.com/search?tbm=isch\u0026q=\\\u0026{func uri_escape $args}\n\n    \u003cpragma-\u003e !img spaces \u0026 stuff\n       \u003cPBot\u003e https://google.com/search?tbm=isch\u0026q=spaces%20%26%20stuff\n\n[Learn more.](doc/Commands.md#substitution)\n\n#### Variables\nYou can use factoids as variables and interpolate them within commands.\n\n    \u003cpragma-\u003e !factadd greeting \"Hello, world\"\n\n    \u003cpragma-\u003e !echo greeting is $greeting\n       \u003cPBot\u003e greeting is Hello, world\n\nPBot variable interpolation supports [expansion modifiers](doc/Factoids.md#expansion-modifiers), which can be chained to\ncombine their effects.\n\n    \u003cpragma-\u003e !echo $greeting:uc\n       \u003cPBot\u003e HELLO, WORLD\n\n[Learn more.](doc/Factoids.md#list-variables)\n\n#### Selectors\nYou can select a random item from a selection list and interpolate the value within commands.\n\n    \u003cpragma-\u003e !echo This is a %(neat|cool|awesome) bot.\n       \u003cPBot\u003e This is a cool bot.\n\n[Learn more.](doc/Commands.md#selectors)\n\n#### Inline invocation\nYou can invoke up to three commands inlined within a message.  If the message\nis addressed to a nick, the output will also be addressed to them.\n\n    \u003cpragma-\u003e newuser13: Check the !{version} and the !{help} documentation.\n       \u003cPBot\u003e newuser13: PBot version 2696 2020-01-04\n       \u003cPBot\u003e newuser13: To learn all about me, see https://github.com/pragma-/pbot/tree/master/doc\n\n[Learn more.](doc/Commands.md#command-invocation)\n\n#### Chaining\nYou can execute multiple commands sequentially as one command.\n\n    \u003cpragma-\u003e !echo Test! ;;; me smiles. ;;; version\n       \u003cPBot\u003e Test! * PBot smiles. PBot version 2696 2020-01-04\n\n[Learn more.](doc/Commands.md#chaining)\n\n#### Background processing\nSuppose you make a Plugin that provides a command that may potentially take a long time to complete?\nNot a problem! You can use the [`cmdset`](doc/Admin.md#cmdset) command to set the `background-process` [command metadata](doc/Admin.md#command-metadata-list)\nand the command will now run as a background process, allowing PBot to carry on with its duties.\n\nThe familiar [`ps`](doc/Admin.md#ps) and [`kill`](doc/Admin.md#kill) commands can be used to list and kill the background processes.\n\nYou can also [`cmdset`](doc/Admin.md#cmdset) the `process-timeout` [command metadata](doc/Admin.md#command-metadata-list) to set the timeout, in seconds, before the command is automatically killed. Otherwise the `processmanager.default_timeout` [registry value](doc/Registry.md) will be used.\n\n### Output customization\n#### Newlines in messages\nBy default, PBot replaces newlines in command output with spaces. This can be customized on a per-channel or global basis\nto instead preserve the newlines and output each line as a distinct message.\n\n[Learn more.](doc/FAQ.md#how-do-i-change-how-the-bot-outputs-multi-line-messages)\n\n#### Truncating long messages\nOutput that is longer than the maximum length of an IRC message will be pasted,\nwith all formatting preserved, to a web paste service. The IRC message itself\nwill be truncated, with enough room to append the paste URL.\n\nWhen `preserve_newlines` is enabled, if there are more lines available than `max_newlines` then\nall of the lines will be pasted, with formatting preserved, to a web paste service. PBot will then\noutput up to `max_newlines` lines as distinct messages and then output the URL to the paste.\n\n### Extensible\nAdditional commands and functionality can  be added to PBot in the following ways.\n\n#### Factoids\nFactoids are a very special type of command. Anybody interacting with PBot\ncan create, edit, delete and invoke factoids.\n\nA simple factoid merely displays the text the creator sets.\n\n    \u003cpragma-\u003e !factadd hello /say Hello, $nick!\n       \u003cPBot\u003e hello added to global channel.\n\n    \u003cpragma-\u003e PBot, hello\n       \u003cPBot\u003e Hello, pragma-!\n\nSignificantly more complex factoids can be built by using `$variables`, command-substitution,\ncommand-piping, `/code` invocation, command prefixes such as `/say`, `/me`, `/msg`, and more!\n\nPBot factoids include these advanced features:\n\n* [undo/redo history](doc/Factoids.md#factundo)\n* [changelog history](doc/Factoids.md#factlog)\n* [channel namespaces](doc/Factoids.md#channel-namespaces)\n* [`factadd`](doc/Factoids.md#factadd) and [`factchange`](doc/Factoids.md#factchange) commands accept a `-url` option that sets the factoid contents from a paste website. In other words, you can edit a factoid's contents using your local editor, preserving line-breaks and indentation.\n* [advanced `$variable` interpolation](doc/Factoids.md#expansion-modifiers) (`$var:lc` to lowercase contents, `$var:ucfirst` to uppercase first letter, etc)\n* [factoid-based variable lists](doc/Factoids.md#list-variables) (e.g., add a factoid `colors` containing \"red green blue\" and then `!echo $colors` will randomly pick one)\n* [advanced argument processing](doc/Factoids.md#special-variables-1) (indexing, splicing, etc)\n* [metadata](doc/Factoids.md#factoid-metadata) (e.g. owner, times used, last used date, locked, etc)\n* [special commands](doc/Factoids.md#special-commands) (`/say`, `/me`, `/msg`, `/code`, etc)\n* and much, much more!\n\nFor more information, see the [Factoids documentation](doc/Factoids.md).\n\n#### Code factoids\nCode factoids are a special type of factoid that executes its contents within a sandboxed virtual machine.\n\nThe contents of code factoids must begin with the `/code` command:\n\n    /code \u003clanguage\u003e \u003ccode\u003e\n\nFor example, the venerable `rot13` function:\n\n    \u003cpragma-\u003e !factadd rot13 /code sh echo \"$@\" | tr a-zA-Z n-za-mN-ZA-M\n       \u003cPBot\u003e rot13 added to global channel.\n\n    \u003cpragma-\u003e !rot13 Pretty neat, huh?\n       \u003cPBot\u003e Cerggl arng, uhu?\n\nMaking a `choose` command:\n\n    \u003cpragma-\u003e !factadd choose /code zsh _arr=($args); print $_arr[$((RANDOM % $#_arr + 1))]\n       \u003cPBot\u003e choose added to global channel.\n\nUsing the `choose` command via an [inlined command](doc/Commands.md#inline-invocation):\n\n    \u003cpragma-\u003e hmm, what should I have for dinner? !{choose chicken \"roast beef\" pizza meatloaf}\n       \u003cPBot\u003e pizza\n\nYou can even pipe output from other commands to Code Factoids.\n\n    \u003cpragma-\u003e !echo test | {rot13}\n       \u003cPBot\u003e grfg\n\nFor more information, see the [Code Factoid documentation](doc/Factoids.md#code).\n\n#### Plugins\nPBot can dynamically load and unload Perl modules to alter its behavior.\n\nThese are some of the plugins that PBot has; [there are many more](lib/PBot/Plugin):\n\nPlugin | Description\n--- | ---\n[ActionTrigger](lib/PBot/Plugin/ActionTrigger.pm) | Lets admins set regular expression triggers to execute PBot commands or factoids.\n[GoogleSearch](lib/PBot/Plugin/GoogleSearch.pm) | Performs Internet searches using the Google search engine.\n[Quotegrabs](lib/PBot/Plugin/Quotegrabs.pm) | Grabs channel messages as quotes for posterity. Can grab messages from anywhere in the channel history. Can grab multiple messages at once!\n[RemindMe](lib/PBot/Plugin/RemindMe.pm) | Lets people set up reminders. Lots of options.\n[Weather](lib/PBot/Plugin/Weather.pm) | Fetches and shows weather data for a location.\n[Wolfram](lib/PBot/Plugin/Wolfram.pm) | Queries Wolfram\\|Alpha for answers.\n[Wttr](lib/PBot/Plugin/Wttr.pm) | Advanced weather Plugin with tons of options. Uses wttr.in.\n[UrlTitles](lib/PBot/Plugin/UrlTitles.pm) | When a URL is seen in a channel, intelligently display its title. It will not display titles that are textually similiar to the URL, in order to maintain the channel signal-noise ratio.\n\nThere are even a few games!\n\nPlugin | Description\n--- | ---\n[Battleship](lib/PBot/Plugin/Battleship.pm) | The classic Battleship board game, simplified for IRC. Multiple players can compete at once on the same battlefield!\n[Connect4](lib/PBot/Plugin/Connect4.pm) | The classic two-player Connect-4 game.\n[Spinach](lib/PBot/Plugin/Spinach.pm) | An advanced multiplayer Trivia game engine with a twist! A question is shown. Everybody privately submits a false answer. All false answers and the true answer is shown. Everybody tries to guess the true answer. Points are gained when people pick your false answer!\n[Wordle](lib/PBot/Plugin/Wordle.pm) | Guess a word by submitting words for clues about which letters belong to the word.\n[WordMorph](lib/PBot/Plugin/WordMorph.pm) | Solve a path between two words by changing one letter at a time.\n\n#### Applets\nApplets are external command-line executable programs and scripts that can be\nloaded as PBot commands.\n\nSuppose you have the [Qalculate!](https://qalculate.github.io/) command-line\nprogram and you want to provide a PBot command for it. You can create a _very_ simple\nshell script containing:\n\n    #!/bin/sh\n    qalc \"$*\"\n\nAnd let's call it `qalc.sh` and put it in PBot's `applets/` directory.\n\nThen you can load it with the [`load`](doc/Admin.md#load) command.\n\n    !load qalc qalc.sh\n\nNow you have a [Qalculate!](https://qalculate.github.io/) calculator in PBot!\n\n    \u003cpragma-\u003e !qalc 2 * 2\n       \u003cPBot\u003e 2 * 2 = 4\n\nThese are just some of the applets PBot comes with; there are several more:\n\nApplet | Description\n--- | ---\n[C-to-English translator](applets/c2english) | Translates C code to natural English sentences.\n[C precedence analyzer](applets/paren) | Adds parentheses to C code to demonstrate precedence.\n[C Jeopardy! game](applets/cjeopardy) | C programming trivia game based on the Jeopardy! TV game show.\n[C Standard citations](applets/cstd.pl) | Cite specified sections/paragraphs from the C standard.\n[Virtual machine](applets/pbot-vm) | Executes arbitrary code and commands within a virtual machine.\n[dict.org Dictionary](applets/dict.org.pl) | Interface to dict.org for definitions, translations, acronyms, etc.\n[Urban Dictionary](applets/urban) | Search Urban Dictionary for definitions.\n[Manpages](applets/man.pl) | Display a concise formatting of manual pages (designed for C functions)\n\nFor more information, see the [Applets documentation](doc/Applets.md).\n\n#### Functions\nFunctions are commands that accept input, manipulate it and then output the result. They are extremely\nuseful with [piping](#piping) or [command substituting](#substitution).\n\nFor example, the `uri_escape` function demonstrated in the [Substitution](#substitution) section earlier\nmakes text safe for use in a URL.\n\n    \u003cpragma-\u003e uri_escape thing's \u0026 words\n       \u003cPBot\u003e thing%27s%20%26%20words\n\nWe also saw the `sed` and `uc` functions demonstrated in [Piping](#piping). The `sed` function\nreplaces text using a substitution regex. The `uc` function uppercases the text.\n\n    \u003cpragma-\u003e echo Hello world! | {sed s/world/universe/} | {uc}\n       \u003cPBot\u003e HELLO UNIVERSE!\n\nHere's a short list of the Functions that come with PBot.\n\nName | Description\n--- | ---\n`uri_escape` | Percent-encodes unsafe URI characters.\n`sed` | Performs sed-like regex substitution.\n`grep` | Searches a string, using a regex, and prints the matching whole-word (e.g. `echo pizza hamburger hotdog \\| {grep burger}` outputs `hamburger`).\n`pluralize` | Intelligently makes a word or phrase plural.\n`unquote` | Removes surrounding quotation marks.\n`title` | Title-cases text. That is, lowercases the text then uppercases the first letter of each word.\n`ucfirst` | Uppercases the first character of the text.\n`uc` | Uppercases all characters.\n`lc` | Lowercases all characters.\n\nAdditional Functions can easily be added by making a very simple PBot Plugin.\n\nFor more information, see the [Functions documentation](doc/Functions.md).\n\n#### Scripting interface\nPBot uses [Plang](https://github.com/pragma-/Plang) as a scripting language. You can use the\nscripting language to construct advanced commands that are capable of interacting with PBot\ninternal API functions.\n\n[Learn more.](doc/Plugins/Plang.md)\n\n### Virtual machine to safely execute user-submitted code\nPBot can integrate with a virtual machine to safely execute arbitrary user-submitted\noperating system commands or code.\n\nPBot supports [several shells and languages](doc/Factoids.md#supported-languages) out of the box!\n\nOne of PBot's most powerful features, [Code Factoids](#code-factoids), would not be possible without this.\n\n    \u003cpragma-\u003e !sh echo Remember rot13? | tr a-zA-Z n-za-mN-ZA-M\n       \u003cPBot\u003e Erzrzore ebg13?\n\n\u003c!-- --\u003e\n\n        \u003cnil\u003e !go package main\\nimport \"fmt\"\\nfunc main() { fmt.Print(\"foo\" == \"foo\"); }\n       \u003cPBot\u003e true\n\n\u003c!-- --\u003e\n\n    \u003cpragma-\u003e !python print('Hello there!')\n       \u003cPBot\u003e Hello there!\n\nPBot has extensive support for the C programming language. For instance, the C programming language\nplugin is integrated with the GNU Debugger. It will print useful debugging information.\n\n    \u003cpragma-\u003e !cc char *p = 0; *p = 1;\n       \u003cPBot\u003e runtime error: store to null pointer of type 'char'\n              Program received signal SIGSEGV, Segmentation fault at\n              statement: *p = 1; \u003clocal variables: p = 0x0\u003e\n\nIt can display the value of the most recent statement if there is no program output.\n\n    \u003cpragma-\u003e !cc sizeof (int)\n       \u003cPBot\u003e no output: sizeof(int) = 4\n\nFor more information about the C programming language plugin, see [the `cc` command in the Applets documentation.](doc/Applets.md#cc)\n\nFor more information about the virtual machine, see the [Virtual Machine documentation.](doc/VirtualMachine.md)\n\n### Powerful user management\nPBot has powerful yet simple user management functionality and commands.\n\n* instead of generic access-levels, PBot uses [fine-grained user capabilities](doc/Admin.md#user-capabilities), which can be grouped into roles such as Admin, ChanOp, Moderator, etc\n* user accounts can be global or channel-specific\n* users can be recognized by hostmask or required to login with password\n* users can adjust their [user-metadata](doc/Admin.md#user-metadata-list) with the [`my`](doc/Commands.md#my) command\n* and much, much more!\n\nFor more information, see the [Admin documentation.](doc/Admin.md#user-management-commands)\n\n### Useful IRC quality-of-life improvements\n* [`mode`](doc/Admin.md#mode) command can take wildcards, e.g. `mode +ov foo* bar*` to op nicks beginning with `foo` and voice nicks beginning with `bar`\n* `unban \u003cnick\u003e` and `unmute \u003cnick\u003e` will remove all bans/mutes matching their current or previously seen hostmasks or accounts\n* [`ban`](doc/Admin.md#banmute) and [`mute`](doc/Admin.md#banmute) will intelligently set banmasks; supports timeouts\n* [`ban`](doc/Admin.md#banmute) and [`mute`](doc/Admin.md#banmute) can take a comma-separate list of nicks. Will intelligently group them into multiple `MODE +bbbb` commands\n* [`kick`](doc/Admin.md#kick) can take a comma-separated list of nicks; also accepts wildcards\n* and much, much more!\n\nFor more information, see the [Admin documentation.](doc/Admin.md)\n\n### Channel management and protection\nPBot can perform the typical channel management tasks.\n\n* opping/deopping known users, etc\n* channel-mode tracking/protection\n* [user hostmask/alias tracking](doc/Admin.md#message-historyuser-tracking)\n* [ban-evasion detection](doc/Admin.md#akalink)\n* [flood detection](doc/AntiAbuse.md)\n* [silent join-flood enforcement](doc/AntiAbuse.md#setting-up-automatic-join-flood-enforcement)\n* whitelisting, blacklisting, etc\n* spam/advertisement detection\n* and much, much more!\n\nFor more information, see the [Channels documentation](doc/Admin.md#channel-management-commands) and the [Anti-abuse documentation](doc/AntiAbuse.md)\n\n### Easy configuration\nPBot's settings are contained in a central registry of key/value pairs grouped by sections.\n\nThese settings can easily be configured via several methods:\n\n* [PBot's command-line arguments](doc/Registry.md#overriding-registry-values-via-command-line)\n* [simple built-in commands (`regset`, `regunset`, etc)](doc/Registry.md#registry-commands)\n* [editing](doc/Registry.md#editing-registry-file) the [`$data_dir/registry`](data/registry) plain-text JSON file\n\nFor more information, see the [Registry documentation.](doc/Registry.md)\n\n### Live reloading of core modules or data files\nSuppose you edit some PBot source file, be it a core file such as [PBot/Core/Interpreter.pm](lib/PBot/Core/Interpreter.pm) or\na Plugin such as [PBot/Plugin/Wttr.pm](lib/PBot/Plugin/Wttr.pm). Or suppose there's a PBot update available. Most simple\nbots would require you to shut down the bot and restart it in order to see the modifications.\n\nNot PBot! you can simply use the [`refresh`](doc/Admin.md#refresh) command to reload all modified\nPBot core files and Plugins without bot restart.\n\nYou can also use the [`reload`](doc/Admin.md#reload) command to reload any modified\nconfiguration or data files.\n\n## Documentation\nSee the [PBot documentation](doc) for more information.\n\n## Frequently Asked Questions\nIf you have a question, try the [PBot FAQ](doc/FAQ.md)!\n\n## Support\nFor additional questions and support, feel free to join the `#pbot` channel on the [Libera.Chat](https://libera.chat/guides) IRC network ([Web Chat](https://web.libera.chat/#pbot)).\n\n## License\nPBot is licensed under the [MIT license](LICENSE).\n","funding_links":[],"categories":["Perl"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpragma-%2Fpbot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpragma-%2Fpbot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpragma-%2Fpbot/lists"}