DBase

Safe IRC Automation: Script Smart and Avoid Floods

Safe IRC Automation: Script Smart and Avoid Floods

Safe IRC Automation: Script Smart and Avoid Floods

• Sep 25, 2026 • 3 views

Learn how to build useful AndroidIRCX automation without reply loops, network floods, unsafe AI commands or nickname-based privilege mistakes.

Safe IRC Automation: Script Smart and Avoid Floods

IRC automation is powerful because a tiny script can react to hundreds of events. That is also the danger: one bad condition can send hundreds of lines, create an infinite reply loop or grant channel privileges to the wrong person.

AndroidIRCX provides rate limits, cached IRC knowledge, confirmation dialogs and recovery controls, but a good script should be safe by design before those defenses are needed.

Technical reference: AndroidIRCX Scripting API


Rule one: never answer yourself

An automatic onMessage reply must ignore messages sent by your own nick:

module.exports = {
  onMessage: msg => {
    if (msg.from === api.userNick) return;
    if (api.strip(msg.text).toLowerCase() === '!ping') {
      api.sendMessage(msg.channel, 'pong');
    }
  },
};

Without that check, a script may process its own echoed message. Two bots with broad triggers can also answer one another forever. Use precise commands or explicit prefixes rather than replying to every line.

Normalize text before matching

IRC formatting codes can sit inside what looks like an ordinary word. Strip them before comparisons:

const text = api.strip(msg.text).trim().toLowerCase();
if (text === '!rules') {
  api.sendMessage(msg.channel, 'Please read the channel topic.');
}

Prefer exact matches or carefully anchored expressions. A check such as text.includes('op') will match innocent words and eventually perform the wrong action.

Rate limits are a seat belt, not a design

AndroidIRCX applies one outbound budget across message, command, action and CTCP paths. It permits a useful burst, then limits sustained output. This protects the network and the user from a runaway loop.

Do not deliberately push against the limit. Batch work, use timers and keep state that prevents duplicate actions.

const announced = api.store.table('announced');

module.exports = {
  onJoin: async (channel, nick) => {
    const key = channel + ':' + nick.toLowerCase();
    if (announced.get(key)) return;

    const saved = await announced.set(key, Date.now(), 24 * 3600_000);
    if (!saved.ok) return;

    api.sendMessage(channel, 'Welcome, ' + nick + '!');
  },
};

The TTL prevents repeated welcomes without building an endless database.

Do not trust a nickname for privileges

Nicknames are temporary labels. If Alice disconnects, another person may be able to take that nick.

For auto-op or other privileged behavior, use a network-verified account and, where appropriate, CertFP information. A null account means the server explicitly reported that the user is logged out; do not treat it as an unknown success.

module.exports = {
  onJoin: (channel, nick) => {
    const user = api.users.get(nick);
    if (!user || user.account !== 'trusted-account') return;
    api.op(channel, nick);
  },
};

The shipped AndroidIRCX Auto-Op example follows this pattern. Auto-voice can use a less privileged policy, but it should still be deliberate.

Read the cache before querying the server

A WHOIS for every incoming message wastes network traffic and can trigger server throttling. AndroidIRCX already maintains user, channel and server knowledge gathered from NAMES, WHO, WHOIS, JOIN, account tags and ISUPPORT.

Use:

  • api.users.get() and api.users.find()
  • api.users.onChannel() and api.users.sharedChannels()
  • api.channelState.get() and api.channelState.getList()
  • api.server.get() and api.server.token()

Remember that a cached list with status unknown is not the same as a fetched empty list.

Use local output for local information

Status text intended only for you belongs in api.echo() or api.log().

api.echo(channel, 'Checked 42 cached users.');

Sending a NOTICE to yourself is still real IRC traffic. On a busy script, that creates unnecessary load and may be throttled.

Confirm dangerous or broad actions

Moderation that affects several users should explain what will happen and ask first:

api.registerCommand('quietunknown', async (args, ctx) => {
  if (!ctx.channel) return;

  const approved = await api.confirm(
    'Apply quiets to unverified users in ' + ctx.channel + '?'
  );

  if (!approved) return;
  // Re-check state here, then perform bounded actions.
});

module.exports = {};

Re-read important state after the confirmation. A channel may change while the dialog is open.

Treat AI output as untrusted text

Channel content can contain prompt-injection attempts. Never pass a model response into api.sendCommand().

Prefer this flow:

  1. Gather only the necessary context.
  2. Call AI with the correct channel and network options.
  3. Display the suggestion with api.echo() or api.setInput().
  4. Let the user edit and send it.

AndroidIRCX's /ai and /aisend split exists for this reason: generation and publication are separate decisions.

Timers and cleanup

Name timers clearly and clear them when disconnected or disabled:

module.exports = {
  onConnect: () => api.setTimer('status-check', 60000, true),
  onTimer: name => {
    if (name === 'status-check') api.log('Periodic check');
  },
  onDisconnect: () => api.clearTimer('status-check'),
  onUnload: () => api.log('Automation stopped'),
};

Do not assume Android will run a timer precisely in the background. Doze, process termination and battery rules can delay or remove execution.

Handle failures as normal states

Storage quotas, revoked permissions, unavailable providers and network failures should not crash a script. Check return values and degrade cleanly.

Avoid enormous synchronous loops. A hook that blocks the app for seconds three times is disabled, but the first long block can still freeze the interface.

Safe release checklist

Before enabling an automation script in a real channel:

  • Run Lint.
  • Test in a private channel.
  • Confirm it ignores its own output.
  • Count every code path that sends IRC traffic.
  • Put an upper bound on loops and batches.
  • Use verified accounts for privileged actions.
  • Use cached state instead of repetitive WHOIS/LIST commands.
  • Prefer echo for private status.
  • Ask before destructive or broad moderation.
  • Keep AI output away from raw commands.
  • Verify cleanup and disable behavior.
  • Watch Script Logs during the first live run.

Good automation should feel quiet. It acts once, for a clear reason, and leaves enough evidence for the user to understand what happened.

Related links

Comments (0)

Log in to leave a comment

No comments yet. Be the first to comment!

Share this post

Found this helpful? Share it with others!

Back

Cookie Consent

We use cookies to enhance your browsing experience, analyze site traffic, and personalize content. By clicking "Accept", you consent to our use of cookies in accordance with our Privacy Policy and GDPR regulations. Learn more