3
0
mirror of https://github.com/pragma-/pbot.git synced 2024-11-16 00:49:35 +01:00
pbot/README.md
2024-03-07 03:17:07 -08:00

433 lines
20 KiB
Markdown

# PBot
PBot is a pragmatic IRCv3 Bot written in Perl
<!-- md-toc-begin -->
* [Installation / Quick Start](#installation--quick-start)
* [Features](#features)
* [IRCv3 capable](#ircv3-capable)
* [Powerful command interpreter](#powerful-command-interpreter)
* [Piping](#piping)
* [Substitution](#substitution)
* [Variables](#variables)
* [Selectors](#selectors)
* [Inline invocation](#inline-invocation)
* [Chaining](#chaining)
* [Background processing](#background-processing)
* [Output customization](#output-customization)
* [Newlines in messages](#newlines-in-messages)
* [Truncating long messages](#truncating-long-messages)
* [Extensible](#extensible)
* [Factoids](#factoids)
* [Code factoids](#code-factoids)
* [Plugins](#plugins)
* [Applets](#applets)
* [Functions](#functions)
* [Scripting interface](#scripting-interface)
* [Virtual machine to safely execute user-submitted code](#virtual-machine-to-safely-execute-user-submitted-code)
* [Powerful user management](#powerful-user-management)
* [Useful IRC quality-of-life improvements](#useful-irc-quality-of-life-improvements)
* [Channel management and protection](#channel-management-and-protection)
* [Easy configuration](#easy-configuration)
* [Live reloading of core modules or data files](#live-reloading-of-core-modules-or-data-files)
* [Documentation](#documentation)
* [Frequently Asked Questions](#frequently-asked-questions)
* [Support](#support)
* [License](#license)
<!-- md-toc-end -->
## Installation / Quick Start
To get up-and-running quickly, check out the [Quick Start guide](doc/QuickStart.md).
## Features
### IRCv3 capable
PBot supports several features of the IRCv3 specification.
* client capability negotiation
* SASL authentication
* account-tag, account-notify, extended-join, message-tags, and more.
### Powerful command interpreter
PBot has a powerful command interpreter with useful functionality, and tons of
built-in commands.
For more information, see the [Commands documentation.](doc/Commands.md)
#### Piping
You can pipe output from one command as input into another command, indefinitely.
<pragma-> !echo hello world | {sed s/world/everybody/} | {uc}
<PBot> HELLO EVERYBODY
[Learn more.](doc/Commands.md#piping)
#### Substitution
You can insert the output from another command at any point within a command. This
substitutes the command with its output at the point where the command was used.
<pragma-> !echo This is &{echo a demonstration} of command substitution
<PBot> This is a demonstration of command substitution
For example, suppose you want to make a Google Image Search command. The naive
way would be to simply do:
<pragma-> !factadd img /call echo https://google.com/search?tbm=isch&q=$args
Unfortuately this would not support queries containing spaces or certain symbols. But
never fear! We can use command substitution and the `uri_escape` function from the
`func` command.
Note that you must escape the command substitution to insert it literally into the
factoid otherwise it will be expanded first.
<pragma-> !factadd img /call echo https://google.com/search?tbm=isch&q=\&{func uri_escape $args}
<pragma-> !img spaces & stuff
<PBot> https://google.com/search?tbm=isch&q=spaces%20%26%20stuff
[Learn more.](doc/Commands.md#substitution)
#### Variables
You can use factoids as variables and interpolate them within commands.
<pragma-> !factadd greeting "Hello, world"
<pragma-> !echo greeting is $greeting
<PBot> greeting is Hello, world
PBot variable interpolation supports [expansion modifiers](doc/Factoids.md#expansion-modifiers), which can be chained to
combine their effects.
<pragma-> !echo $greeting:uc
<PBot> HELLO, WORLD
[Learn more.](doc/Factoids.md#list-variables)
#### Selectors
You can select a random item from a selection list and interpolate the value within commands.
<pragma-> !echo This is a %(neat|cool|awesome) bot.
<PBot> This is a cool bot.
[Learn more.](doc/Commands.md#selectors)
#### Inline invocation
You can invoke up to three commands inlined within a message. If the message
is addressed to a nick, the output will also be addressed to them.
<pragma-> newuser13: Check the !{version} and the !{help} documentation.
<PBot> newuser13: PBot version 2696 2020-01-04
<PBot> newuser13: To learn all about me, see https://github.com/pragma-/pbot/tree/master/doc
[Learn more.](doc/Commands.md#command-invocation)
#### Chaining
You can execute multiple commands sequentially as one command.
<pragma-> !echo Test! ;;; me smiles. ;;; version
<PBot> Test! * PBot smiles. PBot version 2696 2020-01-04
[Learn more.](doc/Commands.md#chaining)
#### Background processing
Suppose you make a Plugin that provides a command that may potentially take a long time to complete?
Not 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)
and the command will now run as a background process, allowing PBot to carry on with its duties.
The familiar [`ps`](doc/Admin.md#ps) and [`kill`](doc/Admin.md#kill) commands can be used to list and kill the background processes.
You 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.
### Output customization
#### Newlines in messages
By default, PBot replaces newlines in command output with spaces. This can be customized on a per-channel or global basis
to instead preserve the newlines and output each line as a distinct message.
[Learn more.](doc/FAQ.md#how-do-i-change-how-the-bot-outputs-multi-line-messages)
#### Truncating long messages
Output that is longer than the maximum length of an IRC message will be pasted,
with all formatting preserved, to a web paste service. The IRC message itself
will be truncated, with enough room to append the paste URL.
When `preserve_newlines` is enabled, if there are more lines available than `max_newlines` then
all of the lines will be pasted, with formatting preserved, to a web paste service. PBot will then
output up to `max_newlines` lines as distinct messages and then output the URL to the paste.
### Extensible
Additional commands and functionality can be added to PBot in the following ways.
#### Factoids
Factoids are a very special type of command. Anybody interacting with PBot
can create, edit, delete and invoke factoids.
A simple factoid merely displays the text the creator sets.
<pragma-> !factadd hello /say Hello, $nick!
<PBot> hello added to global channel.
<pragma-> PBot, hello
<PBot> Hello, pragma-!
Significantly more complex factoids can be built by using `$variables`, command-substitution,
command-piping, `/code` invocation, command prefixes such as `/say`, `/me`, `/msg`, and more!
PBot factoids include these advanced features:
* [undo/redo history](doc/Factoids.md#factundo)
* [changelog history](doc/Factoids.md#factlog)
* [channel namespaces](doc/Factoids.md#channel-namespaces)
* [`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.
* [advanced `$variable` interpolation](doc/Factoids.md#expansion-modifiers) (`$var:lc` to lowercase contents, `$var:ucfirst` to uppercase first letter, etc)
* [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)
* [advanced argument processing](doc/Factoids.md#special-variables-1) (indexing, splicing, etc)
* [metadata](doc/Factoids.md#factoid-metadata) (e.g. owner, times used, last used date, locked, etc)
* [special commands](doc/Factoids.md#special-commands) (`/say`, `/me`, `/msg`, `/code`, etc)
* and much, much more!
For more information, see the [Factoids documentation](doc/Factoids.md).
#### Code factoids
Code factoids are a special type of factoid that executes its contents within a sandboxed virtual machine.
The contents of code factoids must begin with the `/code` command:
/code <language> <code>
For example, the venerable `rot13` function:
<pragma-> !factadd rot13 /code sh echo "$@" | tr a-zA-Z n-za-mN-ZA-M
<PBot> rot13 added to global channel.
<pragma-> !rot13 Pretty neat, huh?
<PBot> Cerggl arng, uhu?
Making a `choose` command:
<pragma-> !factadd choose /code zsh _arr=($args); print $_arr[$((RANDOM % $#_arr + 1))]
<PBot> choose added to global channel.
Using the `choose` command via an [inlined command](doc/Commands.md#inline-invocation):
<pragma-> hmm, what should I have for dinner? !{choose chicken "roast beef" pizza meatloaf}
<PBot> pizza
You can even pipe output from other commands to Code Factoids.
<pragma-> !echo test | {rot13}
<PBot> grfg
For more information, see the [Code Factoid documentation](doc/Factoids.md#code).
#### Plugins
PBot can dynamically load and unload Perl modules to alter its behavior.
These are some of the plugins that PBot has; [there are many more](lib/PBot/Plugin):
Plugin | Description
--- | ---
[ActionTrigger](lib/PBot/Plugin/ActionTrigger.pm) | Lets admins set regular expression triggers to execute PBot commands or factoids.
[GoogleSearch](lib/PBot/Plugin/GoogleSearch.pm) | Performs Internet searches using the Google search engine.
[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!
[RemindMe](lib/PBot/Plugin/RemindMe.pm) | Lets people set up reminders. Lots of options.
[Weather](lib/PBot/Plugin/Weather.pm) | Fetches and shows weather data for a location.
[Wolfram](lib/PBot/Plugin/Wolfram.pm) | Queries Wolfram\|Alpha for answers.
[Wttr](lib/PBot/Plugin/Wttr.pm) | Advanced weather Plugin with tons of options. Uses wttr.in.
[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.
There are even a few games!
Plugin | Description
--- | ---
[Battleship](lib/PBot/Plugin/Battleship.pm) | The classic Battleship board game, simplified for IRC. Multiple players can compete at once on the same battlefield!
[Connect4](lib/PBot/Plugin/Connect4.pm) | The classic two-player Connect-4 game.
[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!
[Wordle](lib/PBot/Plugin/Wordle.pm) | Guess a word by submitting words for clues about which letters belong to the word.
[WordMorph](lib/PBot/Plugin/WordMorph.pm) | Solve a path between two words by changing one letter at a time.
#### Applets
Applets are external command-line executable programs and scripts that can be
loaded as PBot commands.
Suppose you have the [Qalculate!](https://qalculate.github.io/) command-line
program and you want to provide a PBot command for it. You can create a _very_ simple
shell script containing:
#!/bin/sh
qalc "$*"
And let's call it `qalc.sh` and put it in PBot's `applets/` directory.
Then you can load it with the [`load`](doc/Admin.md#load) command.
!load qalc qalc.sh
Now you have a [Qalculate!](https://qalculate.github.io/) calculator in PBot!
<pragma-> !qalc 2 * 2
<PBot> 2 * 2 = 4
These are just some of the applets PBot comes with; there are several more:
Applet | Description
--- | ---
[C-to-English translator](applets/c2english) | Translates C code to natural English sentences.
[C precedence analyzer](applets/paren) | Adds parentheses to C code to demonstrate precedence.
[C Jeopardy! game](applets/cjeopardy) | C programming trivia game based on the Jeopardy! TV game show.
[C Standard citations](applets/cstd.pl) | Cite specified sections/paragraphs from the C standard.
[Virtual machine](applets/pbot-vm) | Executes arbitrary code and commands within a virtual machine.
[dict.org Dictionary](applets/dict.org.pl) | Interface to dict.org for definitions, translations, acronyms, etc.
[Urban Dictionary](applets/urban) | Search Urban Dictionary for definitions.
[Manpages](applets/man.pl) | Display a concise formatting of manual pages (designed for C functions)
For more information, see the [Applets documentation](doc/Applets.md).
#### Functions
Functions are commands that accept input, manipulate it and then output the result. They are extremely
useful with [piping](#piping) or [command substituting](#substitution).
For example, the `uri_escape` function demonstrated in the [Substitution](#substitution) section earlier
makes text safe for use in a URL.
<pragma-> uri_escape thing's & words
<PBot> thing%27s%20%26%20words
We also saw the `sed` and `uc` functions demonstrated in [Piping](#piping). The `sed` function
replaces text using a substitution regex. The `uc` function uppercases the text.
<pragma-> echo Hello world! | {sed s/world/universe/} | {uc}
<PBot> HELLO UNIVERSE!
Here's a short list of the Functions that come with PBot.
Name | Description
--- | ---
`uri_escape` | Percent-encodes unsafe URI characters.
`sed` | Performs sed-like regex substitution.
`grep` | Searches a string, using a regex, and prints the matching whole-word (e.g. `echo pizza hamburger hotdog \| {grep burger}` outputs `hamburger`).
`pluralize` | Intelligently makes a word or phrase plural.
`unquote` | Removes surrounding quotation marks.
`title` | Title-cases text. That is, lowercases the text then uppercases the first letter of each word.
`ucfirst` | Uppercases the first character of the text.
`uc` | Uppercases all characters.
`lc` | Lowercases all characters.
Additional Functions can easily be added by making a very simple PBot Plugin.
For more information, see the [Functions documentation](doc/Functions.md).
#### Scripting interface
PBot uses [Plang](https://github.com/pragma-/Plang) as a scripting language. You can use the
scripting language to construct advanced commands that are capable of interacting with PBot
internal API functions.
[Learn more.](doc/Plugins/Plang.md)
### Virtual machine to safely execute user-submitted code
PBot can integrate with a virtual machine to safely execute arbitrary user-submitted
operating system commands or code.
PBot supports [several shells and languages](doc/Factoids.md#supported-languages) out of the box!
One of PBot's most powerful features, [Code Factoids](#code-factoids), would not be possible without this.
<pragma-> !sh echo Remember rot13? | tr a-zA-Z n-za-mN-ZA-M
<PBot> Erzrzore ebg13?
<!-- -->
<nil> !go package main\nimport "fmt"\nfunc main() { fmt.Print("foo" == "foo"); }
<PBot> true
<!-- -->
<pragma-> !python print('Hello there!')
<PBot> Hello there!
PBot has extensive support for the C programming language. For instance, the C programming language
plugin is integrated with the GNU Debugger. It will print useful debugging information.
<pragma-> !cc char *p = 0; *p = 1;
<PBot> runtime error: store to null pointer of type 'char'
Program received signal SIGSEGV, Segmentation fault at
statement: *p = 1; <local variables: p = 0x0>
It can display the value of the most recent statement if there is no program output.
<pragma-> !cc sizeof (int)
<PBot> no output: sizeof(int) = 4
For more information about the C programming language plugin, see [the `cc` command in the Applets documentation.](doc/Applets.md#cc)
For more information about the virtual machine, see the [Virtual Machine documentation.](doc/VirtualMachine.md)
### Powerful user management
PBot has powerful yet simple user management functionality and commands.
* 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
* user accounts can be global or channel-specific
* users can be recognized by hostmask or required to login with password
* users can adjust their [user-metadata](doc/Admin.md#user-metadata-list) with the [`my`](doc/Commands.md#my) command
* and much, much more!
For more information, see the [Admin documentation.](doc/Admin.md#user-management-commands)
### Useful IRC quality-of-life improvements
* [`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`
* `unban <nick>` and `unmute <nick>` will remove all bans/mutes matching their current or previously seen hostmasks or accounts
* [`ban`](doc/Admin.md#banmute) and [`mute`](doc/Admin.md#banmute) will intelligently set banmasks; supports timeouts
* [`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
* [`kick`](doc/Admin.md#kick) can take a comma-separated list of nicks; also accepts wildcards
* and much, much more!
For more information, see the [Admin documentation.](doc/Admin.md)
### Channel management and protection
PBot can perform the typical channel management tasks.
* opping/deopping known users, etc
* channel-mode tracking/protection
* [user hostmask/alias tracking](doc/Admin.md#message-historyuser-tracking)
* [ban-evasion detection](doc/Admin.md#akalink)
* [flood detection](doc/AntiAbuse.md)
* [silent join-flood enforcement](doc/AntiAbuse.md#setting-up-automatic-join-flood-enforcement)
* whitelisting, blacklisting, etc
* spam/advertisement detection
* and much, much more!
For more information, see the [Channels documentation](doc/Admin.md#channel-management-commands) and the [Anti-abuse documentation](doc/AntiAbuse.md)
### Easy configuration
PBot's settings are contained in a central registry of key/value pairs grouped by sections.
These settings can easily be configured via several methods:
* [PBot's command-line arguments](doc/Registry.md#overriding-registry-values-via-command-line)
* [simple built-in commands (`regset`, `regunset`, etc)](doc/Registry.md#registry-commands)
* [editing](doc/Registry.md#editing-registry-file) the [`$data_dir/registry`](data/registry) plain-text JSON file
For more information, see the [Registry documentation.](doc/Registry.md)
### Live reloading of core modules or data files
Suppose you edit some PBot source file, be it a core file such as [PBot/Core/Interpreter.pm](lib/PBot/Core/Interpreter.pm) or
a Plugin such as [PBot/Plugin/Wttr.pm](lib/PBot/Plugin/Wttr.pm). Or suppose there's a PBot update available. Most simple
bots would require you to shut down the bot and restart it in order to see the modifications.
Not PBot! you can simply use the [`refresh`](doc/Admin.md#refresh) command to reload all modified
PBot core files and Plugins without bot restart.
You can also use the [`reload`](doc/Admin.md#reload) command to reload any modified
configuration or data files.
## Documentation
See the [PBot documentation](doc) for more information.
## Frequently Asked Questions
If you have a question, try the [PBot FAQ](doc/FAQ.md)!
## Support
For 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)).
## License
PBot is licensed under the [MIT license](LICENSE).