> For the complete documentation index, see [llms.txt](https://docs.nighty.one/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.nighty.one/custom-features-tab/conditions.md).

# Conditions

[Filters](/custom-features-tab/filters.md) were the bouncer at the door - broad checks about *where* and *who*. **Conditions are the detailed inspection** that happens next.

This is where you ask specific questions about what actually happened: does the message contain this word? Does this person have that role? Is this channel named something in particular?

{% hint style="info" %}
**Your goal with conditions is simple: make sure only the events you actually care about reach your actions.**
{% endhint %}

## 1. The condition collection

Conditions don't sit loose in your feature - they live inside a **condition collection**.

Each collection contains four things:

| Part                  | What it's for                                               |
| --------------------- | ----------------------------------------------------------- |
| **My Values**         | Values you work out once and reuse. Covered on its own page |
| **Conditions**        | The checks themselves, optionally grouped                   |
| **If met** actions    | Actions that run when the checks pass                       |
| **Otherwise** actions | Actions that run when the checks fail                       |

**The most basic setup is: add your conditions, and leave everything else untouched.** The defaults do the sensible thing - if the conditions pass, your feature carries on to its actions; if they don't, it stops.

That covers most features. The "If met / Otherwise" parts are there for when you want something more interesting, and they're explained in [section 6](#id-6.-advanced-if-met-otherwise).

You can have **more than one collection**. They're checked in order, top to bottom. For a first feature, one is plenty.

## 2. Every condition must pass

By default, when you add conditions, **all of them have to pass** before the event moves on to your actions. One failure and the feature stops there.

{% hint style="info" %}
If a condition runs into an error - for example it checks a message that isn't there - it counts as **not passed**, and the reason is written to your feature's log.
{% endhint %}

## 3. AND and OR - the connector

Conditions are joined by a **connector**.

<figure><img src="/files/cP02vAuG2ffIgdPAWnVN" alt=""><figcaption></figcaption></figure>

It's set to **AND** by default, and clicking it switches it to **OR**.

The difference is the whole game:

| Connector | Passes when                                             |
| --------- | ------------------------------------------------------- |
| **AND**   | **Every** condition passes. All of them, no exceptions. |
| **OR**    | **At least one** condition passes. The rest can fail.   |

**AND makes your feature pickier.** Each condition you add narrows it further.

**OR makes it more accepting.** Each condition you add is another way in.

### AND example

> Message contains **"invoice"**\
> **AND**\
> Message has an attachment

<figure><img src="/files/CVv9zjWwSIRJXh71egzT" alt=""><figcaption></figcaption></figure>

This only fires for messages that have *both* - the word *and* a file. A message saying "Here's the invoice" with nothing attached doesn't pass. Neither does a random screenshot with no text.

### OR example

> Message contains **"invoice"**\
> **OR**\
> Message has an attachment

<figure><img src="/files/hZhQbnh3YaMT84vTlz6q" alt=""><figcaption></figcaption></figure>

This fires if *either* is true. You usually want AND in such case.

{% hint style="warning" %}
**The connector applies to the whole group, not to one pair of conditions.** Switching one connector switches them all in that group. If you need *some* conditions joined by AND and others by OR, that's what groups are for.
{% endhint %}

## 4. Groups

<figure><img src="/files/U1f6Og6pkZO89lbsPHT9" alt=""><figcaption></figcaption></figure>

A group is a set of conditions with its own connector. **You can have up to two groups per collection.**

That gives you three connectors to set:

* The connector **inside group 1**
* The connector **inside group 2**
* The connector **between the two groups**

This is what lets you build things a single flat list can't express.

### Why you need them

Say you want: *messages about deals, but only in the deals channels.*

Written as one flat list, it's impossible - you'd need "OR" between the deal words and "AND" between the words and the channels, and a flat list only has one connector.

With groups it's straightforward:

> **Group 1** *(OR)*\
> Message contains **"sale"**\
> OR Message contains **"discount"**
>
> **— AND —**
>
> **Group 2** *(OR)*\
> Channel is **#deals**\
> OR Channel is **#promos**

Read it out loud: *"(sale or discount) and (deals or promos)."* A "sale" message in #general doesn't pass. A "hello" message in #deals doesn't pass. Only a deal word in a deal channel gets through.

### Another example

*"Tell me about messages that mention me from friends, and about anything marked urgent regardless of who sent it."*

> **Group 1** *(AND)*\
> Message mentions me\
> AND Message is from a user on my whitelist
>
> **— OR —**
>
> **Group 2** *(AND)*\
> Message contains **"urgent"**

Read it out loud: *"(mentions me and is from a friend) or (contains urgent)."*

### The trick for getting it right

**Say your rule out loud in plain English first**, then put the brackets where you naturally pause. Whatever's inside a bracket becomes a group, and the word at the pause becomes the connector between them.

* *"(A or B) and C"* → group 1 holds A and B joined by OR; group 2 holds C; between them, AND
* *"A and (B or C)"* → group 1 holds A; group 2 holds B and C joined by OR; between them, AND

## 5. What happens when conditions pass

Nothing dramatic - the event moves on to the next collection, and once all the collections are done, to your feature's **final actions**.

That's the whole basic flow:

**Event → Filters → Conditions → Actions**

If you never touch If met / Otherwise, that's all conditions ever do: let events through, or stop them.

## 6. Advanced - If met / Otherwise

<figure><img src="/files/7kSraJehlMSGCCM7uEHC" alt=""><figcaption></figcaption></figure>

Here's where a feature stops being a straight line.

**By default, when your conditions aren't met, the feature just stops.** Nothing runs. That's usually what you want.

But each collection can also carry its own actions, which run *right there*, before the feature's final actions:

* **If met** actions run when the collection **passes**\
  ![](/files/MRiKvGy5uROPhWAMvZw6)
* **Otherwise** actions run when the collection **fails**\
  ![](/files/ZJj5tcuR2efT5cquwxCt)

And each side has a setting for what happens **afterwards**.

{% hint style="info" %}
**The most important rule here:** the action block **always runs**. If the collection passes, its "If met" actions run - full stop. The flow setting only decides what happens *after* those actions have finished. It never cancels them.
{% endhint %}

### After "If met", you can choose:

<figure><img src="/files/cPsGVgrvTRwsAv9jiqjY" alt=""><figcaption></figcaption></figure>

| Option                        | What happens next                                                               |
| ----------------------------- | ------------------------------------------------------------------------------- |
| **Continue** *(default)*      | Move on to the next collection, as normal                                       |
| **Continue to final actions** | Skip any remaining collections and jump straight to the feature's final actions |
| **Stop**                      | End the feature here. The final actions do **not** run                          |

### After "Otherwise", you can choose:

<figure><img src="/files/doC87EO9pxoZu2SL1IcF" alt=""><figcaption></figcaption></figure>

| Option               | What happens next                                      |
| -------------------- | ------------------------------------------------------ |
| **Stop** *(default)* | End the feature here. The final actions do **not** run |
| **Continue**         | Move on to the next collection anyway                  |

### Example 1 - a fallback message

*"Only let approved people use this, and tell everyone else no."*

> **Collection 1**\
> Condition: user is on my approved list\
> **If met:** *(nothing)* → Continue\
> **Otherwise:** reply "Sorry, you're not on the list" → Stop
>
> **Final actions:** do the actual thing

Approved people sail past the collection and reach the final actions. Everyone else gets the reply and stops. Without the "Otherwise" block they'd just get silence.

### Example 2 - a command router

This is the pattern that makes multiple collections worth using.

> **Collection 1**\
> Condition: message is exactly `!weather`\
> **If met:** send the weather → **Stop**\
> **Otherwise:** → **Continue**
>
> **Collection 2**\
> Condition: message is exactly `!time`\
> **If met:** send the time → **Stop**\
> **Otherwise:** → **Stop**

One feature, two commands. Each collection checks for its own command, does its job, and stops so the next one never runs. The last "Otherwise → Stop" catches everything that matched neither.

Note that "Otherwise → Continue" in collection 1 is doing real work: it's what lets a `!time` message get past the weather check to reach collection 2. With the default (Stop), collection 2 would never be reached.

### Example 3 - a shortcut for VIPs

> **Collection 1**\
> Condition: user is on my VIP list\
> **If met:** send a personal greeting → **Continue to final actions**\
> **Otherwise:** → **Continue**
>
> **Collection 2**\
> Conditions: the normal checks everyone else has to pass\
> **If met:** → Continue\
> **Otherwise:** → Stop
>
> **Final actions:** log it to my private channel

VIPs get their greeting and jump straight to the logging, skipping the checks they don't need to pass. Everyone else goes through collection 2 the normal way. Both paths end at the same final actions, so the logging happens either way.

That's the difference between **Stop** and **Continue to final actions**: Stop ends everything, while Continue to final actions skips the remaining *checks* but still does the *work* at the end.

## 7. Two things to know

{% hint style="info" %}
**If met / Otherwise actions count as a run.** As soon as one of those blocks actually has actions in it and gets executed, it counts against your [execution limits](/custom-features-tab/execution-limits.md), the same as a normal run would. A collection that passes but has an empty "If met" block doesn't count for anything on its own.
{% endhint %}

{% hint style="info" %}
**My Values are ready before the checks run.** Any My Values in a collection are worked out first, before its conditions are evaluated - and they're worked out whether the collection ends up passing or failing. So your conditions, your "If met" actions and your "Otherwise" actions can all use them. They get their own page.
{% endhint %}
