mirror of
https://github.com/FoxxMD/context-mod.git
synced 2026-01-15 00:18:06 -05:00
492 lines
15 KiB
Markdown
492 lines
15 KiB
Markdown
# Table Of Contents
|
|
|
|
* [Overview](#overview)
|
|
* [Lifecycle](#lifecycle)
|
|
* Window Components
|
|
* [Range](#range)
|
|
* [Count](#count)
|
|
* [Duration](#duration)
|
|
* [Duration String](#duration-string-recommended)
|
|
* [Duration Object](#duration-object)
|
|
* [Specifying Range](#specifying-range)
|
|
* [Specifying Activity Type](#types-of-activities)
|
|
* [Filters](#filters)
|
|
* [Properties](#filter-properties)
|
|
* [Lifecycle](#filter-lifecycle)
|
|
* [`pre`](#pre-filter)
|
|
* [`post`](#post-filter)
|
|
* [More Examples](#more-examples)
|
|
* [Count](#count-examples)
|
|
* [Duration](#duration-examples)
|
|
* [Count And Duration](#count-and-duration-examples)
|
|
* [Activity Types](#activity-type-examples)
|
|
* [Filter](#filter-examples)
|
|
|
|
# Overview
|
|
|
|
An **Activity Window** (`window`) is a group of properties that describe a **range** of [**Activities**](/docs/README.md#activity) to retrieve from Reddit and how to **filter** them.
|
|
|
|
The main components of an Activity Window:
|
|
|
|
* **Range** -- How many Activities ([`count`](#count)) or what time period ([`duration`](#duration)) of Activities to fetch
|
|
* **Type of Activities** -- When **fetching** from an Author's history, should it return overview (any Activities), just Submissions, or just Comments?
|
|
* **Filters** -- How the retrieved Activities should be [filtered](/docs/subreddit/components/README.md#filters) before returning them to a Rule
|
|
|
|
|
|
As an example, if you want to run a **Recent Activity Rule** to check if a user has had activity in /r/mealtimevideos you also need to define what range of activities you want to look at from that user's history.
|
|
|
|
## Lifecycle
|
|
|
|
Understanding the lifecycle for how CM uses the Activity Window to retrieve Activities is important to effectively using it.
|
|
|
|
```mermaid
|
|
graph TD
|
|
RangReq["Determine Range requirements (Parse `count` and `duration` values)"] --> EmptyList>Create empty Activities List]
|
|
EmptyList --> Fetch>"Fetch Activities chunk (1 API Call)"]
|
|
Fetch --> PreFilter>Invoke `pre` filter on Activities from chunk]
|
|
PreFilter --> Add[Add filtered chunk to Activities list]
|
|
Add --> CheckRange>Check Range Satisfaction]
|
|
CheckRange -->|`count` Range| CountReq[Are there `count` # of Activities?]
|
|
CheckRange -->|`duration` Range| DurationReq[Is the oldest Activity `duration` old?]
|
|
CheckRange -->|`count` and `duration` Range| CountDurReq[Is either `count` and/or `duration` satisfied?]
|
|
|
|
|
|
CountReq -->|No| Fetch
|
|
DurationReq -->|No| Fetch
|
|
CountDurReq -->|No| Fetch
|
|
|
|
CountReq -->|Yes| FetchDone
|
|
DurationReq -->|Yes| FetchDone
|
|
CountDurReq -->|Yes| FetchDone
|
|
|
|
FetchDone[Fetch Complete] --> PostFilter>Invoke `post` filter on all Activities]
|
|
PostFilter --> Return>Return Activities to Rule]
|
|
|
|
click PreFilter href "#pre-filter"
|
|
click PostFilter href "#post-filter"
|
|
click CountReq href "#count"
|
|
click DurationReq href "#duration"
|
|
click CountDurReq href "#specifying-range"
|
|
```
|
|
|
|
# Range
|
|
|
|
There are two types of values that can be used when defining a range:
|
|
|
|
## Count
|
|
|
|
This is the **number** of activities you want to retrieve. It's straightforward -- if you want to look at the last 100 activities for a user you can use `100` as the value.
|
|
|
|
### Shorthand
|
|
|
|
If **count** is the only property you want to define (leaving everything else as default) then `window` can be defined with just this value:
|
|
|
|
```yaml
|
|
window: 70 # retrieve 70 activities
|
|
```
|
|
****
|
|
Otherwise, use the `count` property on a full `window` object:
|
|
|
|
```yaml
|
|
window:
|
|
count: 70 # retrieve 70 activities
|
|
...
|
|
```
|
|
|
|
## Duration
|
|
|
|
A **duration of time** between which all activities will be retrieved. This is a **relative value** that calculates the actual range based on **the duration of time subtracted from when the rule is run.**
|
|
|
|
For example:
|
|
|
|
* Today is **July 15th**
|
|
* You define a duration of **10 days**
|
|
|
|
Then the range of activities to be retrieved will be between **July 5th and July 15th** (10 days).
|
|
|
|
### Shorthand
|
|
|
|
If a Duration string is the only property you want to define (leaving everything else as default) then `window` can be defined with just this value:
|
|
|
|
```yaml
|
|
window: '9 days' # retrieve last 9 days of activities
|
|
```
|
|
|
|
Otherwise, use the `duration` property on a full `window` object:
|
|
|
|
```yaml
|
|
window:
|
|
duration: '9 days'
|
|
...
|
|
```
|
|
|
|
### Duration Types
|
|
|
|
The value used to define the duration can be **one of these two types**:
|
|
|
|
#### Duration String (recommended)
|
|
|
|
A string consisting of
|
|
|
|
* A [Dayjs unit of time](https://day.js.org/docs/en/durations/creating#list-of-all-available-units)
|
|
* The value of that unit of time
|
|
|
|
Examples:
|
|
|
|
* `9 days`
|
|
* `14 hours`
|
|
* `80 seconds`
|
|
|
|
You can ensure your string is valid by testing it [here.](https://regexr.com/61em3)
|
|
|
|
##### As ISO 8601 duration string
|
|
|
|
If you're a real nerd you can also use a [standard duration](https://en.wikipedia.org/wiki/ISO_8601#Durations) string.
|
|
|
|
Examples
|
|
|
|
* `PT15M` (15 minutes)
|
|
|
|
Ensure your string is valid by testing it [here.](https://regexr.com/61em9)
|
|
|
|
#### Duration Object
|
|
|
|
If you need to specify multiple units of time for your duration you can instead provide a [Dayjs duration **object**](https://day.js.org/docs/en/durations/creating#list-of-all-available-units) consisting of Dayjs unit-values.
|
|
|
|
```yaml
|
|
window:
|
|
duration:
|
|
days: 4
|
|
hours: 6
|
|
minutes: 20
|
|
```
|
|
|
|
## Specifying Range
|
|
|
|
You may use **one or both range properties.**
|
|
|
|
If both range properties are specified then the value `satisfyOn` determines how the final range is determined
|
|
|
|
|
|
### Using `satisfyOn: any` (default)
|
|
|
|
If **any** then Activities will be retrieved until one of the range properties is met, **whichever occurs first.**
|
|
|
|
```yaml
|
|
window:
|
|
count: 80
|
|
duration: 90 days
|
|
satisfyOn: any
|
|
```
|
|
Activities are retrieved in chunks of 100 (or `count`, whichever is smaller)
|
|
|
|
* If 90 days of activities returns only 40 activities => returns 40 activities
|
|
* If 80 activities is only 20 days of range => 80 activities
|
|
|
|
### Using `satisfyOn: all`
|
|
|
|
If **all** then both ranges must be satisfied. Effectively, whichever range produces the most Activities will be the one that is used.
|
|
|
|
```yaml
|
|
window:
|
|
count: 100
|
|
duration: 90 days
|
|
satisfyOn: all
|
|
```
|
|
Activities are retrieved in chunks of 100 (or `count`, whichever is smaller)
|
|
|
|
* If at 90 days of activities => 40 activities retrieved
|
|
* continue retrieving results until 100 activities
|
|
* so range is >90 days of activities
|
|
* If at 100 activities => 20 days of activities retrieved
|
|
* continue retrieving results until 90 days of range
|
|
* so results in >100 activities
|
|
|
|
# Types of Activities
|
|
|
|
When retrieving an Author's history the window can specify if it should return all Activities (overview), just Comments, or just Submissions, using the `fetch` property:
|
|
|
|
```yaml
|
|
window:
|
|
# defaults to 'overview'
|
|
fetch: 'submission' # must be one of: overview, comment, submission
|
|
```
|
|
|
|
# Filters
|
|
|
|
Activity Window can also specify [Item and Subreddit Filters](/docs/subreddit/components/README.md#filters) to filter the Activities retrieved from Reddit before they are returned to a Rule.
|
|
|
|
Activities can be filtered **during** (`pre`) retrieval or **after** (`post`) retrieval. **When**, during the window **lifecycle**, the Activities are filtered can change the set of Activities returned to a Rule drastically.
|
|
|
|
## Filter Properties
|
|
|
|
Regardless of when you are filtering Activities the shape of the filter is the same. Filter properties:
|
|
|
|
* `subreddits` -- A [Filter Shape](/docs/subreddit/components/README.md#filter-shapes) for filtering by the [Subreddit Criteria](/docs/subreddit/components/README.md#subreddit-filter) of each Activity
|
|
* `submissionState` -- A [Filter Shape](/docs/subreddit/components/README.md#filter-shapes) for [Submission Criteria](/docs/subreddit/components/README.md#item-filter). Will run only if filtering a Submission.
|
|
* `commentState` -- A [Filter Shape](/docs/subreddit/components/README.md#filter-shapes) for [Comment Criteria](/docs/subreddit/components/README.md#item-filter). Will run only if filtering a Comment.
|
|
* `activityState` -- A [Filter Shape](/docs/subreddit/components/README.md#filter-shapes) for either [Submission or Comment Criteria](/docs/subreddit/components/README.md#item-filter). Will run only if `submissionState` or `commentState` is not defined for their respective Activity types.
|
|
|
|
In this example the filter only returns Activities:
|
|
|
|
* With a subreddit that
|
|
* Is from the subreddit /r/mealtimevideos OR
|
|
* Has a name that matches the regex `/ask.*/i` (starts with `ask`) OR
|
|
* Is marked as NSFW
|
|
* AND if the Activity is a Submission:
|
|
* must be self text
|
|
* AND if the Activity is a Comment (because `activityState` is defined and `commentState` is not):
|
|
* Comment is NOT removed
|
|
|
|
```yaml
|
|
subreddits:
|
|
include:
|
|
- 'mealtimevideos'
|
|
- '/ask.*/i'
|
|
- over18: true
|
|
|
|
submissionState:
|
|
include:
|
|
- is_self: true
|
|
|
|
activityState:
|
|
exclude:
|
|
- removed: false
|
|
```
|
|
|
|
## Filter Lifecycle
|
|
|
|
Filters can be independently specified for two different "locations" during the window lifecycle using the `filterOn` property.
|
|
|
|
### `pre` Filter
|
|
|
|
`pre` will filter Activities from **each API call, before** they are added to the full list of retrieved Activities and, most importantly, **before CM checks if Range conditions have been satisfied.** See the [Lifecycle Diagram](#lifecycle).
|
|
|
|
This is useful when you want the Range conditions to be applied to an "already filtered" list of Activities -- as opposed to afterwards (like `post`).
|
|
|
|
#### `max` restriction
|
|
|
|
However, `pre` introduces the possibility of **near impossible range conditions.**
|
|
|
|
For example, if you want 200 activities from a subreddit a user has never created activities in then CM would fetch the user's **entire history** before finishing since each chunk of Activities would be filtered to 0.
|
|
|
|
To prevent this scenario all `pre` filters must also specify a `max` [range](#range) that tell CM:
|
|
|
|
> if X range of **non-filtered** Activities is reached stop immediately
|
|
|
|
#### `pre` Example
|
|
|
|
Let's follow an example scenario where you want the last 200 activities a user has in /r/mealtimevideos
|
|
|
|
```yaml
|
|
window:
|
|
count: 200
|
|
filterOn:
|
|
pre:
|
|
subreddits:
|
|
include:
|
|
- mealtimevideos
|
|
max: 400
|
|
```
|
|
|
|
* CM fetches the first chunk of 100 Activities (100 total unfiltered)
|
|
* `pre` Filter finds 70 of those 100 are from /r/mealtimevideos => Total Filtered Activities 70
|
|
* CM Checks range condition => 70 is less than 200
|
|
* CM Checks max condition => 100 unfiltered is less than 400
|
|
* CM fetches second chunk of 100 Activities (200 total unfiltered)
|
|
* `pre` Filter finds another 70 of those 100 are from /r/mealtimevideos => Total Filtered Activities 140
|
|
* CM Checks range condition => 140 is less than 200
|
|
* CM Checks max condition => 200 unfiltered is less than 400
|
|
* CM fetches third chunk of 100 activities (300 total unfiltered)
|
|
* `pre` Filter finds 90 of those 100 are from /r/mealtimevideos => Total Filtered Activities 230
|
|
* CM checks range condition => 230 is more than 200
|
|
* CM Checks max condition => 300 unfiltered is less than 400
|
|
|
|
**CM is done fetching activities with 230 Filtered Activities**
|
|
|
|
Now let's look at the same scenario but `max` is hit:
|
|
|
|
* CM fetches the first chunk of 100 Activities (100 total unfiltered)
|
|
* `pre` Filter finds 10 of those 100 are from /r/mealtimevideos => Total Filtered Activities 10
|
|
* CM Checks range condition => 10 is less than 200
|
|
* CM Checks max condition => 100 unfiltered is less than 400
|
|
* CM fetches second chunk of 100 Activities (200 total unfiltered)
|
|
* `pre` Filter finds another 15 of those 100 are from /r/mealtimevideos => Total Filtered Activities 25
|
|
* CM Checks range condition => 25 is less than 200
|
|
* CM Checks max condition => 200 unfiltered is less than 400
|
|
* CM fetches third chunk of 100 activities (300 total unfiltered)
|
|
* `pre` Filter finds 5 of those 100 are from /r/mealtimevideos => Total Filtered Activities 30
|
|
* CM checks range condition => 30 is less than 200
|
|
* CM Checks max condition => 300 unfiltered is less than 400
|
|
* CM fetches fourth chunk of 100 activities (400 total unfiltered)
|
|
* `pre` Filter finds 0 of those 100 are from /r/mealtimevideos => Total Filtered Activities 30
|
|
* CM checks range condition => 30 is less than 200
|
|
* CM Checks max condition => 400 unfiltered is NOT less than 400
|
|
* CM stops fetching due to max condition hit
|
|
|
|
**CM is done fetching activities with 30 Filtered Activities**
|
|
|
|
### `post` Filter
|
|
|
|
`post` will filter the full list of Activities **after range conditions are satisfied**. This also means it receives the list of Activities filtered by the [`pre` filter](#pre-filter), if one is defined.
|
|
|
|
The list returned by `post` is what the Rule receives.
|
|
|
|
#### Example
|
|
|
|
Let's follow an example scenario where you want to get the last 200 activities from a User's history **and then** return any of those 200 that were made in /r/mealtimevideos -- contrast this wording to the [`pre` example](#pre-example)
|
|
|
|
```yaml
|
|
window:
|
|
count: 200
|
|
filterOn:
|
|
post:
|
|
subreddits:
|
|
include:
|
|
- mealtimevideos
|
|
```
|
|
|
|
* CM fetches the first chunk of 100 Activities (100 total unfiltered)
|
|
* CM checks range condition => 100 is less than 200
|
|
* CM fetches the second chunk of 100 Activities (200 total unfiltered)
|
|
* CM checks range condition => 200 is equal to 200
|
|
* CM is done fetching activities with 200 unfiltered Activities
|
|
* `post` filter finds 10 of those 200 are from /r/mealtimevideos
|
|
* CM returns 10 Activities to the Rule
|
|
|
|
# More Examples
|
|
|
|
### Count Examples
|
|
|
|
#### Get last 100 activities in a User's history
|
|
|
|
```yaml
|
|
window: 100
|
|
```
|
|
or
|
|
|
|
```yaml
|
|
window:
|
|
count: 100
|
|
```
|
|
|
|
### Duration Examples
|
|
|
|
#### Get last 2 weeks of a User's history
|
|
|
|
```yaml
|
|
window: '2 weeks'
|
|
```
|
|
or
|
|
|
|
```yaml
|
|
window:
|
|
duration: '2 weeks'
|
|
```
|
|
|
|
#### Get last 24 hours and 30 minutes of User's history
|
|
|
|
```yaml
|
|
window:
|
|
duration:
|
|
hours: 24
|
|
minutes: 30
|
|
```
|
|
|
|
### Count and Duration Examples
|
|
|
|
#### Get EITHER last 6 months or last 200 activities of User's history
|
|
|
|
Whichever is [satisifed first](#using-satisfyon-any-default)
|
|
|
|
```yaml
|
|
window:
|
|
count: 200
|
|
duration: '6 months'
|
|
```
|
|
|
|
#### Get AT LEAST the last 6 months and last 200 activities of User's history
|
|
|
|
Both must be [satisifed](#using-satisfyon-all)
|
|
|
|
```yaml
|
|
window:
|
|
count: 200
|
|
duration: '6 months'
|
|
satisfyOn: 'all'
|
|
```
|
|
|
|
### Activity Type Examples
|
|
|
|
#### Get the last 200 submissions from User's history
|
|
|
|
```yaml
|
|
window:
|
|
count: 200
|
|
fetch: 'submission'
|
|
```
|
|
|
|
#### Get the last 200 comments from User's history
|
|
|
|
```yaml
|
|
window:
|
|
count: 200
|
|
fetch: 'comment'
|
|
```
|
|
|
|
#### Get the last 200 activities (submissions or comments) from User's history
|
|
|
|
```yaml
|
|
window:
|
|
count: 200
|
|
fetch: 'overview' # or do not include 'fetch' at all, this is the default
|
|
```
|
|
|
|
### Filter Examples
|
|
|
|
#### Get the all activities from NSFW subreddits in the User's last 200 activities
|
|
|
|
```yaml
|
|
window:
|
|
count: 200
|
|
filterOn:
|
|
post:
|
|
subreddits:
|
|
include:
|
|
- over18: true
|
|
```
|
|
|
|
#### Get the all comments from NSFW subreddits where user is OP, in the User's last 200 activities
|
|
|
|
```yaml
|
|
window:
|
|
count: 200
|
|
fetch: 'comment'
|
|
filterOn:
|
|
post:
|
|
subreddits:
|
|
include:
|
|
- over18: true
|
|
commentState:
|
|
include:
|
|
- op: true
|
|
```
|
|
|
|
#### Get the last 200 self-text submissions from a User's history and return any from ask* subreddits
|
|
|
|
```yaml
|
|
window:
|
|
count: 200
|
|
fetch: 'submission'
|
|
filterOn:
|
|
pre:
|
|
submissionState:
|
|
include:
|
|
- is_self: true
|
|
max: 500
|
|
post:
|
|
subreddits:
|
|
include:
|
|
- '/ask.*/i'
|
|
```
|