- Reusable templates — named regex fragments referenced with
!name!syntax - Mapping rules — a small DSL for renaming, regrouping, and enriching content
Template loading
Templates can live in three places:| Location | How to configure |
|---|---|
Inline in source.yml | templates: block at the top level |
Inline in mapping.yml | templates: block inside mappings: |
| Central file or directory | template_path in config.yml |
*.yml files are loaded in alphanumeric order and merged. Template names must be globally unique across all sources.
Template syntax
Define templates as named string values:! characters:
value.
mapping.yml structure
The top-level mappings key holds:
| Key | Description |
|---|---|
templates | Reusable template definitions (same format as source.yml) |
mapping | List of mapping entries |
| Field | Description |
|---|---|
id | Unique identifier — referenced from targets in source.yml |
match_as_ascii | Normalize Unicode to ASCII before matching |
mapper | List of mapper rules (filter + script pairs) |
counter | List of counter rules for injecting sequence numbers |
match_as_ascii
When enabled, Tuliprox deunicodes field values before applying filters. This lets simple ASCII patterns match content with accented or special characters:
é→eö→oß→ss
Mapper rules
Each mapper rule contains:| Field | Description |
|---|---|
filter | Filter expression — only matching entries run this script |
script | DSL script to execute |
Mapper DSL reference
Accessing playlist fields
Playlist fields are accessed with the@Field syntax. Fields can also be assigned to update the output:
| Variable | Description |
|---|---|
@Group | Channel group name |
@Title | Channel title |
@Name | Channel name |
@Caption | Channel caption |
@Url | Stream URL |
@Genre | Content genre |
@Input | Source input name |
Variable assignment
Regex capture
Regex matches expose numbered captures via.1, .2, etc., and named captures via .name:
match block
Select a value based on which variables are truthy:
map block
Map a variable’s value to a new value:
for_each
Iterate over split values or regex capture groups:
Nested map blocks
map blocks can be nested:
Built-in functions
| Function | Description |
|---|---|
concat(a, b, ...) | Concatenate strings |
uppercase(s) | Convert to uppercase |
lowercase(s) | Convert to lowercase |
capitalize(s) | Capitalize first letter |
trim(s) | Remove leading and trailing whitespace |
print(s) | Print a value to debug output |
number(s) | Parse a string as a number |
first(a, b, ...) | Return the first non-null value |
template(name) | Expand a named template |
replace(s, pattern, replacement) | Regex replace |
pad(n, width) | Zero-pad a number |
format(fmt, ...) | Format string with positional args |
add_favourite(group) | Add the current channel to a favourite group |
split(s, pattern) | Split a string on a regex pattern |
Counters
Counters inject auto-incrementing sequence numbers into channel titles or group names.| Field | Description |
|---|---|
filter | Filter expression — only matching entries get a counter |
value | Starting counter value |
field | Field to apply the counter to: title, group, etc. |
modifier | prefix or suffix |
concat | Separator string between counter and field value |
padding | Minimum digit width (zero-padded) |
Complete mapping.yml example
Advanced grouping example
This script groups channels into quality-oriented or category-oriented buckets:Grouping by release year
Filter hints
Filters in mapper rules use the same expression language as target filters:| Operator | Description |
|---|---|
~ | Regex match |
NOT | Logical negation |
AND | Logical conjunction |
OR | Logical disjunction |
Type = live|vod|series | Match by content type |