📢 PhantomBot v3.7.0.0 is now available as a stable build
⚠️ Due to upcoming changes by Twitch, IRC slash/dot commands are now moved to the Helix Twitch API. These new endpoints require new OAuth scopes by Twitch to function. Both the Bot (Chat) and Broadcaster (API) OAuths must be re-done after updating to v3.6.5.1 or later. This is also required for Purge/Timeout/Ban!
⚠️ The URL for the OAuth page has been normalized. If OAuth authorization is failing, please check the redirect URI in the Twitch Developer Console exactly matches the URI provided in step 1.6 on the OAuth setup page
⭐ Major Changes
➡️ The Guides are now split into nightly and stable channels. Use the widget in the nav bar to switch channels
Additionally, the Command Tags Guide now separates the command tags into separate headings, based on the name of the script which defined them
➡️ Channel Points redemptions now support custom command tags
- Terminology for Channel Points has been standardized within PhantomBot to reduce confusion
- redeemable is used to refer to a Channel Points Reward on Twitch
- redemption is used to refer to an individual redemption of a Channel Points Reward
- redeeming is used in reference to the user who redeemed the Channel Points Reward
- reward is used (on all lines below and in PhantomBot) to refer to the responses and rewards that a PhantomBot instance is configured to trigger in response to a redemption
- Channel Points support requires the broadcaster (API) OAuth token to actually belong to the broadcaster
- New scopes are required to create, edit, delete, or manage redeemables and redemptions
- ⚠️ WARNING: When a reward for a Channel Points redemption is triggered, the
(sender)
will be the bot and the command tags will be executed with ADMIN permissions - Channel Points rewards and redeemables can be managed via the panel, under the Loyalty section
- Each redeemable may be linked to a single reward
- Command tags for getting redeemable/redemption info and setting the redemption status can be found in the channelpoints section of the Command Tags guide
- Rewards support all command tags which have both the
twitch
label and any one ofchannelpointsevent
,commandevent
,noevent
- NOTE: If the redeeming user enters new lines (ENTER, aka. LF or
\n
) into the input prompt, they will be URL-encoded to%0A
- NOTE: A custom command is not required to use this functionality, the command tags can be directly entered into the script
- When managing rewards through Twitch chat, some sub-actions to
!channelpoints
require a(reward id)
. Once you add a reward, you can get the(reward id)
and human-readable titles from!channelpoints list
➡️ Channel Points redeemables and redemptions can now be managed via the API
- Twitch Limitation: requires bot to create/convert to an API redeemable first
- Requires the broadcaster (API) OAuth token to actually belong to the broadcaster
➡️ HTTPWSServer now supports directly accessing X.509 SSL certificates without using a JKS
Requirements to Setup:
- A PEM format certificate file containing the entire X.509 certificate chain from self to the root authority
- A PEM format certificate file containing a PKCS#8 private key
- An optional password on the private key
- Set
httpsFileName
in botlogin.txt to the path to the X.509 certificate chain file - Set
httpsKeyFileName
in botlogin.txt to the path to the PKCS#8 private key file - Set
httpsPassword
in botlogin.txt to the private key password. Omit this setting if a password is not used
NOTE: Both httpsFileName
and httpsKeyFileName
must be defined to use X.509 certificates. If only httpsFileName
is defined, it will be treated as a JKS. If httpsFileName
is not defined, auto-generated self-signed SSL certificates will be used
NOTE: Due to limitations in the available methods for loading X.509 certificates, the X.509 certificate chain file (httpsFileName
) must contain the full chain from self to the root authority
➡️ The Rhino JS engine now defaults to ES6 support enabled
For information on the functionality this enables, see the 1.7.14 column on the Rhino Compatibility Table. The features with the yellow Flag 🏴 indication are enabled by this change
➡️ Raffles now support drawing winners without locking/closing entries. This is a setting which must be toggled on
➡️ Added the Setup page to the bots webserver, allowing access to most botlogin.txt values. This page is now used instead of the console for first-time setup
- ENV variables and manual editing/copying of botlogin.txt are still supported methods of performing first-time setup
- ⚠️ WARNING: By default, this page can be accessed using the panel login and will reveal some secret keys, such as the Twitch Application Client Secret. It is strongly recommended to set the allowpanelusertosetup flag to
false
immediately, especially if the panel login is shared with others. - When the allowpanelusertosetup flag is set to
false
, the only way to access the setup page will be via a one-time username/password which is printed to console upon trying to access the page - Some properties still may not take effect after saving until the bot is restarted
- 🐞 Known limitation: If a random person tries to visit the setup page while you are using it, they will invalidate your one-time username/password. If you had used this method to login to the setup page, then saving changes may fail until login is performed again with a new one-time username/password
- 🐞 Intentional limitation: The page only displays settings defined in the properties.json file, which is auto-generated by parsing the Java code on build. Custom properties are excluded unless manually added to this file
- The following variables are not accessible from the Setup page:
- "apiexpires",
- "apioauth",
- "apirefresh",
- "appsecret",
- "apptoken",
- "apptokenexpires",
- "backupsqliteauto",
- "backupsqlitehourfrequency",
- "backupsqlitekeepdays",
- "newsetup",
- "oauth",
- "oauthexpires",
- "refresh",
- "rollbarid",
- "twitter_access_token",
- "twitter_refresh_token",
- "webauth",
- "webauthro",
- "ytauth",
- "ytauthro"
- Any other property not added to the properties.json file
➡️ Discord commands and keywords now use the new command tags system
- Removed
$.discord.tags
- Removed Discord tag
(touser=)
. The regular(touser)
tag still works - NOTE: Some tags may work differently between Discord and Twitch. For example, on Twitch
(uptime)
returns a message if the stream is offline, while Discord will silently cancel the entire command
➡️ Shield Mode enable/disable is supported by making a command/trigger respond with /shield
or /shieldoff
NOTE: The broadcaster (API) OAuth must be re-done to acquire a new scope. This endpoint accepts the broadcaster or any channel moderator
➡️ Changed event handling to allow custom scripts to hook ircModeration
event. This allows implementation of custom moderation processing similar to chatMod
// Subscribe to event
$.bind('ircModeration', function(event) {
// Some custom isBad function checks the message
if (isBad(event.getMessage())) {
try {
// Timeout the user
$.timeoutUser(event.getSender(), 1, 'Just a purge');
// Using try-finally to ensure an exception while
// timing out doesn't block this from emitting
} finally {
// Notify Mono subscribers to stop processing
// due to timeout being issued
event.moderated();
}
}
});
ℹ️ The event
object is IrcModerationEvent
with the following methods
String event.getSender()
the senderString event.getMessage()
the messageMap<String, String> event.getTags()
the IRCv3 tagsMono<Boolean> event.mono()
a Mono that emitstrue
ifevent.moderated()
has been calledvoid event.moderated()
emitstrue
from the Mono, indicating that moderation action has been taken and processing of the message should stopboolean event.isCommand()
returnstrue
if the message looks like a !commandCommandEvent event.asCommand()
returns the message as aCommandEvent
, as used in$.bind('command',
. Returnsnull
ifevent.isCommand()
returnedfalse
ℹ️ OnPrivMessage processing is now handled as follows
- Check for ACTION and convert message text to /me
- Print message to console
- Update UsernameCache
- Handle sending IrcChannelUserModeEvent
- Handle IrcModerationEvent
- If IrcModerationEvent returns
false
(No hook calledevent.moderated()
), continue processing sub/bits/commands/message
⚠️ WARNING: If IrcModerationEvent takes longer than 5 seconds total for all hooks to run, it is assumed that no moderation occurred (returns false
in last step above)
➡️ Changed the parameters for command tag transformers
The function signature of $.transformers.tags
is now
$.transformers.tags(event, message, globalTransformerRequiredLabels, args)
event - The event object
message - The response message containing tags to parse
globalTransformerRequiredLabels - The array of labels indicating which tags to allow. Labels are `&&` together, and therefore required, except for a single-level sub-array, which creates an `&& (x || y)`. Default ['twitch', ['commandevent', 'noevent']]
args - a JS Object which can contain the following optional keys
{
atEnabled - Default `false`. If `true`, *platform* is 'twitch', there are no tags, (sender) is a moderator, and an argument is present: responds with @(1) -> message
globalTransformerAnyLabels - An array of labels which are `||` together, checked after globalTransformerRequiredLabels
localTransformers - a JS Object of custom transformers used just for this call {"tagName": function, ...}
customArgs - an arbitrary JS Object of custom arguments
platform - identifies the platform that triggered the command. Valid values: 'twitch', 'discord'. Default: 'twitch'
}
The function signature for a transformer is now
function foo(args)
args - a JS Object
{
event: event object,
tag: tag name,
args: tag arguments as a single string,
customArgs: args.customArgs,
globalTransformerRequiredLabels: globalTransformerRequiredLabels,
globalTransformerAnyLabels: args.globalTransformerAnyLabels,
platform: args.platform.toLowerCase()
}
➡️ The (command)
tag no longer cancels tag processing, allowing multiple (command)
or other tags to be used in a single response
Full Changelog
✅ Added:
➡️ Added overload PhantomBot.generateRandomString(int length, boolean allowSpecial)
that enables special characters if allowSpecial is set to true
, according to the allowed characters for PKCE (gmt2001)
➡️ Added the js global $.helix
, which provides easy access to tv.phantombot.twitch.api.Helix.instance()
(gmt2001)
➡️ Added the Channel Points redeemables endpoints to Helix (gmt2001)
➡️ Added an update task to convert old channelpointsHandler reward types transfer, giveAll, emoteOnly, and timeout into new command tag responses, if they were enabled (gmt2001)
➡️ Added some ReentrantLocks to many scripts. This should fix saving issues when multiple tasks within the script execute (Sartharon #2960)
➡️ Added the ability to set a minimum viewer threshold for raidHandler to trigger (BrandenB)
➡️ Added the ability to use X.509 certificate files without a JKS for HTTPWSServer SSL configuration (gmt2001)
➡️ Added the ability for HTTPWSServer to automatically find a port up to 20 numbers higher than baseport
if baseport
is already in use. The new port number will be saved to botlogin.txt (gmt2001)
➡️ Added command tag (url0a2nl)
which converts %0A
into \n
(gmt2001)
➡️ Added command tag (nl2br)
which converts \n
into <br>
(gmt2001)
➡️ Added command tags (add)
, (addall)
, (take)
, (takeall)
, and (transfer)
which are equivalent to the similarly-named !points
sub-actions (gmt2001)
➡️ Added command tag (readfileall)
which returns an entire file, including newlines (ENTER, aka. LF or \n
) (gmt2001)
➡️ Added command tag (delaycommand)
, which is the same as (command)
, except it waits a specified number of seconds before triggering the downstream command (gmt2001)
➡️ Added command tag (delaysay)
, which waits a specified number of seconds before sending the specified message to chat (gmt2001)
➡️ Added an additional formula for (pointname)
which gets either the singular or plural name of the bot currency, based on an input number of points (gmt2001)
➡️ Added command tag (sanitizeuser)
which performs some basic sanitziation of Twitch usernames (gmt2001)
➡️ Added command tag (escape)
which escapes all parenthasis ( )
on the input to prevent command tag processing (gmt2001)
➡️ Added command tags to set the bots Discord presence (current activity) (gmt2001)
➡️ Added botlogin.txt property discord_restore_presence (default false
). If true
, then the Discord presence is saved and restored across restarts (gmt2001)
➡️ Added URI com.gmt2001.httpclient.URIUtil.create(String uri)
as a drop-in replacement for java.net.URI.create(String uri)
to auto-correct invalid characters in most URIs (gmt2001)
➡️ Added hook ircPong
to detect when Twitch sends a PONG command (gmt2001)
➡️ Added the ability to enable/disable Twitch Shield Mode by redirecting /shield
and /shieldoff
to the API (gmt2001)
➡️ Added optional on/off parameter to !notice toggleid, making the new signature !notice toggleid (notice id) [on/off]
, to force the notice to the desired state (gmt2001)
➡️ Added the ability to specify that wsEvent
should require the script to send a reply, instead of an auto-ack from the bots webserver (gmt2001)
➡️ Added $.panel.sendObject(event.getId(), jsObject)
, $.panel.sendArray(event.getId(), jsArray)
, and $.panel.sendAck(event.getId())
for scripts to send responses to wsEvent
(gmt2001)
➡️ Added generic functions socket.query(type, query_id, params, callback)
and socket.update(type, query_id, params, callback)
to the panel for sending WS messages that do and do-not (respectively) require response data (gmt2001)
➡️ Added helpers.querymap
to the panel, containing a map of query parameters from the URI used to load the panel (gmt2001)
➡️ Added the ability to craft a panel link to jump to a specific page on load /panel/?folder=FOLDERNAME&page=PAGENAME
(FOLDERNAME is the data-folder
attribute from the left nav menu such as settings, PAGENAME is the name of the file such as localization.html) (gmt2001)
➡️ Added the ability to link a Twitter account to the bot from the panel (🔗 icon on the Twitter box of the Alerts panel page) (gmt2001)
🌀 Changed:
➡️ Changed Twitter functions to use the official Twitter SDK (gmt2001)
➡️ Rewrote channelpointsHandler to use custom command tag processing (gmt2001 #2470 #2480)
➡️ Moved the Logger
, BTTVAPIv3
, and YouTubeAPIv3
Java classes to the com.illusionaryone
namespace (gmt2001)
➡️ Changed HTTPWSServer and WSClient to use native sockets when available, increasing speed and decreasing resource usage (gmt2001)
➡️ Changed healthcheck.py and associated scripts to use IRC PING/PONG to check connection state (gmt2001)
➡️ Changed all methods which previously used the user=
property in botlogin.txt to instead get the login name associated with the current bot (chat) OAuth token (gmt2001)
➡️ Changed ticketRaffle so that when more winners are drawn from the same raffle after the first draw, it only outputs the new winners to chat (gmt2001)
➡️ Changed the panel dashboard to display current subscriber count instead of total lifetime views (gmt2001)
➡️ Changed various sections of the bots HTTP server to return 405 Method Not Allowed when using an invalid HTTP method for an endpoint (gmt2001)
➡️ Changed bot initialization to automatically remove colon :
from the paneluser (gmt2001)
➡️ Updated SQLite to 3.39.4.1 (gmt2001)
➡️ Changed the timeout for the isAdmin check on Discord to reduce failures and to default to false
if it still times out (gmt2001)
➡️ Changed the function signatures for $.transformers.tags
and for transformer functions. See above in the Major Changes section (gmt2001)
➡️ Changed the scope warnings for Purge/Timeout/Ban functionality to check and warn about the bot (chat) token (gmt2001)
➡️ Changed (command)
to not cancel tag processing and to pass event.getTags()
to the downstream command (gmt2001)
➡️ Changed (command)
to use $.parseArgs
(gmt2001)
➡️ Changed guide links on the panel to set the channel to nightly if running from a nightly (non-custom) build (gmt2001)
➡️ Changed helpers.getDropdownGroup
in the panel to support the same attributes (_id, name, value, selected, disabled) as the other dropdown functions (gmt2001)
➡️ Changed Helix to always return the actual response code in the jso.status
field on a non-200 response, even when jso.error
is Not JSON (gmt2001)
➡️ Changed welcomeSystem to use the new tags processor to handle it's tags (does not support any additional tags compared to before, however) (gmt2001)
➡️ Changed ircModeration
hook to be accessible to all scripts, allowing custom moderation handlers to be implemented (gmt2001)
➡️ Changed the order of processing for PrivMsgTMIProcessor to account for blocking processing if moderation actions are triggered (gmt2001)
🛠️ Fixed:
➡️ Fixed PhantomBot.generateRandomString
having the character 0
defined twice in the allowed characters source, potentially lowering randomness of the result (gmt2001)
➡️ Fixed console/debug output for the alerts page erroneously indicating that a supported audio file format could not be found (gmt2001)
➡️ Fixed DiscordAPI not using CompositeAddressResolverGroup, leading to potential DNS failures for Discord functions in certain setups (gmt2001)
➡️ Fixed Helix
not using com.gmt2001.ExecutorService
, causing unnecessary creation of additional threads (gmt2001)
➡️ Fixed YouTube title searches failing due to the query string not being URL-encoded (gmt2001, reported by gnkidwell #2998)
➡️ Fixed YouTube title searches failing due to not recognizing HTTP 4xx/5xx responses (gmt2001, reported by gnkidwell #2998)
➡️ Fixed raidHandler sometimes not recognizing usernames due to the presence of @
(gmt2001)
➡️ Fixed raidHandler sometimes not recording that a raid occurred if the response message had no text left after tag processing (gmt2001)
➡️ Fixed an issue where a failed sound alert could cause all future sound alerts to not trigger unless the alerts overlay page was refreshed (Psychoboy #2970)
➡️ Fixed an issue where raffles and ticket raffles could pull the same user multiple times when doing a multi-winner draw (gmt2001)
➡️ Fixed an NPE when accessing a WS URI on the bots webserver that contains ..
(gmt2001)
➡️ Fixed an issue where spaces were removed from an alias when edited via the panel (gmt2001)
➡️ Fixed an issue where exclamation points (!
) that were not in the prefix were removed from an alias when edited (gmt2001)
➡️ Fixed !coolcom
/cooldown module not allowing to set the cooldown for a command to 0
(no cooldown) without editing the database (gmt2001)
➡️ Fixed !notice toggleid
indicating the opposite state (printing enabled when result is disabled) into chat when the command completed (gmt2001)
➡️ Fixed launch.bat not supporting launching directly into Windows Terminal on Windows 11 (gmt2001)
➡️ Fixed welcomeSystem not replacing (names)
with user1 and user2 if only 2 users were being welcomed. Uses new lang string welcomesystem.names.join3 (name chosen to avoid conflict with existing edits) (gmt2001)
➡️ Fixed incoming IRC messages being processed by scripts after chatMod determined that the user should be purged/timed out/banned (gmt2001)
➡️ Fixed $.banUser
not being exported as a standardized function to send a /ban
(gmt2001)
🗑️ Deprecated:
➡️ com.gmt2001.HttpRequest
is Deprecated and should not be used for new development. com.gmt2001.httpclient.HttpClient
should be used instead
➡️ tv.phantombot.PhantomBot.getProperties()
is deprecated and should not be used for new development. tv.phantombot.CaselessProperties.instance()
should be used instead
➡️ com.gmt2001.TwitchAPIv5
is Deprecated and should not be used for new development. tv.phantombot.twitch.api.Helix
should be used instead
🛑 Removed:
➡️ Removed old channelpointsHandler reward types transfer, giveAll, emoteOnly, and timeout (gmt2001)
➡️ Removed $.modListUsers
(and the related $.hasModList
) as it wasn't ever populated (gmt2001)
➡️ Removed support for the Twitch total lifetime view count stat, as Twitch has deprecated and stopped updating it (gmt2001)
➡️ Removed $.performModeration
(gmt2001)
➡️ Removed the property user=
from botlogin.txt (gmt2001)
🐞 Known Issues:
➡️ The new Twitter SDK only supports TwitterAPIv2, which does not support Media Uploads, so the Twitch Thumbnail is not uploaded to tweets anymore by twitterHandler
🌐 Download It:
➡️ Downloads attached to the bottom of this release notice
❗ Remember to install to a separate folder, then copy over the config dir, as well as any custom scripts or files in addons
➡️ PhantomBot official builds are available on GitHub Container Registry at ghcr.io/phantombot/phantombot and ghcr.io/phantombot/nightly-build
➡️ PhantomBot official builds are available on DockerHub at gmt2001/phantombot-stable and gmt2001/phantombot-nightly. See the readme text on the appropriate Docker Hub pages for Docker Compose files
🗒️ Notes:
➡️ We have guides on PhantomBot. You can contribute by submitting a Pull Request adding or editing .md files in the /docs/guides/content folder of the repo. See the guides for info about formatting.