@tracearr/shared 2.2.0-beta.2 → 2.2.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/automations/__tests__/actions.test.d.ts +2 -0
- package/dist/automations/__tests__/actions.test.d.ts.map +1 -0
- package/dist/automations/__tests__/actions.test.js +68 -0
- package/dist/automations/__tests__/actions.test.js.map +1 -0
- package/dist/automations/__tests__/conditions.test.d.ts +2 -0
- package/dist/automations/__tests__/conditions.test.d.ts.map +1 -0
- package/dist/automations/__tests__/conditions.test.js +55 -0
- package/dist/automations/__tests__/conditions.test.js.map +1 -0
- package/dist/automations/__tests__/definition.test.d.ts +2 -0
- package/dist/automations/__tests__/definition.test.d.ts.map +1 -0
- package/dist/automations/__tests__/definition.test.js +376 -0
- package/dist/automations/__tests__/definition.test.js.map +1 -0
- package/dist/automations/__tests__/share.test.d.ts +2 -0
- package/dist/automations/__tests__/share.test.d.ts.map +1 -0
- package/dist/automations/__tests__/share.test.js +98 -0
- package/dist/automations/__tests__/share.test.js.map +1 -0
- package/dist/automations/__tests__/templates.test.d.ts +2 -0
- package/dist/automations/__tests__/templates.test.d.ts.map +1 -0
- package/dist/automations/__tests__/templates.test.js +278 -0
- package/dist/automations/__tests__/templates.test.js.map +1 -0
- package/dist/automations/__tests__/triggers.test.d.ts +2 -0
- package/dist/automations/__tests__/triggers.test.d.ts.map +1 -0
- package/dist/automations/__tests__/triggers.test.js +42 -0
- package/dist/automations/__tests__/triggers.test.js.map +1 -0
- package/dist/automations/actions.d.ts +783 -0
- package/dist/automations/actions.d.ts.map +1 -0
- package/dist/automations/actions.js +97 -0
- package/dist/automations/actions.js.map +1 -0
- package/dist/automations/conditions.d.ts +459 -0
- package/dist/automations/conditions.d.ts.map +1 -0
- package/dist/automations/conditions.js +460 -0
- package/dist/automations/conditions.js.map +1 -0
- package/dist/automations/definition.d.ts +1389 -0
- package/dist/automations/definition.d.ts.map +1 -0
- package/dist/automations/definition.js +215 -0
- package/dist/automations/definition.js.map +1 -0
- package/dist/automations/dryRun.d.ts +413 -0
- package/dist/automations/dryRun.d.ts.map +1 -0
- package/dist/automations/dryRun.js +9 -0
- package/dist/automations/dryRun.js.map +1 -0
- package/dist/automations/index.d.ts +8 -0
- package/dist/automations/index.d.ts.map +1 -0
- package/dist/automations/index.js +8 -0
- package/dist/automations/index.js.map +1 -0
- package/dist/automations/share.d.ts +27 -0
- package/dist/automations/share.d.ts.map +1 -0
- package/dist/automations/share.js +119 -0
- package/dist/automations/share.js.map +1 -0
- package/dist/automations/templates.d.ts +1304 -0
- package/dist/automations/templates.d.ts.map +1 -0
- package/dist/automations/templates.js +525 -0
- package/dist/automations/templates.js.map +1 -0
- package/dist/automations/triggers.d.ts +141 -0
- package/dist/automations/triggers.d.ts.map +1 -0
- package/dist/automations/triggers.js +177 -0
- package/dist/automations/triggers.js.map +1 -0
- package/dist/constants.d.ts +22 -40
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +25 -56
- package/dist/constants.js.map +1 -1
- package/dist/destinations.d.ts +21 -22
- package/dist/destinations.d.ts.map +1 -1
- package/dist/destinations.js +13 -2
- package/dist/destinations.js.map +1 -1
- package/dist/index.d.ts +10 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -9
- package/dist/index.js.map +1 -1
- package/dist/listQuery.d.ts +41 -0
- package/dist/listQuery.d.ts.map +1 -0
- package/dist/listQuery.js +33 -0
- package/dist/listQuery.js.map +1 -0
- package/dist/media.d.ts +2 -0
- package/dist/media.d.ts.map +1 -1
- package/dist/media.js +2 -1
- package/dist/media.js.map +1 -1
- package/dist/schemas.d.ts +152 -832
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +90 -287
- package/dist/schemas.js.map +1 -1
- package/dist/types.d.ts +51 -137
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/violations.d.ts +2 -1
- package/dist/violations.d.ts.map +1 -1
- package/dist/violations.js +7 -0
- package/dist/violations.js.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export type TriggerContext = 'session' | 'account' | 'media' | 'server' | 'install';
|
|
3
|
+
/** Whether a trigger of this context carries everything `requires` names. */
|
|
4
|
+
export declare function contextSupplies(context: TriggerContext, requires: TriggerContext): boolean;
|
|
5
|
+
/** What a trigger is about, and what the list filters on. */
|
|
6
|
+
export declare const TRIGGER_GROUPS: readonly ["sessions", "accounts", "library", "servers", "updates"];
|
|
7
|
+
export type TriggerGroup = (typeof TRIGGER_GROUPS)[number];
|
|
8
|
+
export declare const TRIGGERS: {
|
|
9
|
+
readonly 'session.started': {
|
|
10
|
+
readonly context: "session";
|
|
11
|
+
readonly group: "sessions";
|
|
12
|
+
readonly variables: readonly ["user.username", "user.identityName", "session.mediaTitle", "session.mediaType", "server.name", "server.type"];
|
|
13
|
+
};
|
|
14
|
+
readonly 'session.stopped': {
|
|
15
|
+
readonly context: "session";
|
|
16
|
+
readonly group: "sessions";
|
|
17
|
+
readonly variables: readonly ["user.username", "user.identityName", "session.mediaTitle", "session.mediaType", "server.name", "server.type", "durationMinutes"];
|
|
18
|
+
};
|
|
19
|
+
readonly 'session.transcode_changed': {
|
|
20
|
+
readonly context: "session";
|
|
21
|
+
readonly group: "sessions";
|
|
22
|
+
readonly variables: readonly ["user.username", "user.identityName", "session.mediaTitle", "session.mediaType", "server.name", "server.type"];
|
|
23
|
+
};
|
|
24
|
+
readonly 'session.paused': {
|
|
25
|
+
readonly context: "session";
|
|
26
|
+
readonly group: "sessions";
|
|
27
|
+
readonly variables: readonly ["user.username", "user.identityName", "session.mediaTitle", "session.mediaType", "server.name", "server.type"];
|
|
28
|
+
};
|
|
29
|
+
readonly 'session.held_for': {
|
|
30
|
+
readonly context: "session";
|
|
31
|
+
readonly group: "sessions";
|
|
32
|
+
readonly variables: readonly ["user.username", "user.identityName", "session.mediaTitle", "session.mediaType", "server.name", "server.type", "minutes"];
|
|
33
|
+
};
|
|
34
|
+
readonly 'account.inactive_for': {
|
|
35
|
+
readonly context: "account";
|
|
36
|
+
readonly group: "accounts";
|
|
37
|
+
readonly variables: readonly ["user.username", "user.identityName", "server.name", "server.type", "days"];
|
|
38
|
+
};
|
|
39
|
+
readonly 'account.new_device': {
|
|
40
|
+
readonly context: "session";
|
|
41
|
+
readonly group: "accounts";
|
|
42
|
+
readonly variables: readonly ["user.username", "user.identityName", "session.mediaTitle", "session.mediaType", "server.name", "server.type", "device.name", "device.platform", "device.product", "device.location"];
|
|
43
|
+
};
|
|
44
|
+
readonly 'account.trust_changed': {
|
|
45
|
+
readonly context: "account";
|
|
46
|
+
readonly group: "accounts";
|
|
47
|
+
readonly variables: readonly ["user.username", "user.identityName", "server.name", "server.type", "trust.previous", "trust.new", "trust.reason"];
|
|
48
|
+
};
|
|
49
|
+
readonly 'media.added': {
|
|
50
|
+
readonly context: "media";
|
|
51
|
+
readonly group: "library";
|
|
52
|
+
readonly variables: readonly ["media.title", "media.name", "media.show", "media.season", "media.episode", "media.episodeCount", "media.type", "media.year", "media.library", "media.server", "server.name", "server.type"];
|
|
53
|
+
};
|
|
54
|
+
readonly 'media.upgraded': {
|
|
55
|
+
readonly context: "media";
|
|
56
|
+
readonly group: "library";
|
|
57
|
+
readonly variables: readonly ["media.title", "media.name", "media.show", "media.season", "media.episode", "media.episodeCount", "media.type", "media.year", "media.library", "media.server", "server.name", "server.type", "media.from.resolution", "media.to.resolution", "media.from.dynamicRange", "media.to.dynamicRange", "media.from.videoCodec", "media.to.videoCodec", "media.from.audioCodec", "media.to.audioCodec", "media.from.audioChannels", "media.to.audioChannels", "media.from.fileSize", "media.to.fileSize"];
|
|
58
|
+
};
|
|
59
|
+
readonly 'server.down': {
|
|
60
|
+
readonly context: "server";
|
|
61
|
+
readonly group: "servers";
|
|
62
|
+
readonly variables: readonly ["server.name", "server.type"];
|
|
63
|
+
};
|
|
64
|
+
readonly 'server.up': {
|
|
65
|
+
readonly context: "server";
|
|
66
|
+
readonly group: "servers";
|
|
67
|
+
readonly variables: readonly ["server.name", "server.type"];
|
|
68
|
+
};
|
|
69
|
+
readonly 'plugin.update_available': {
|
|
70
|
+
readonly context: "server";
|
|
71
|
+
readonly group: "updates";
|
|
72
|
+
readonly variables: readonly ["server.name", "server.type", "installedVersion", "latestVersion", "downloadUrl"];
|
|
73
|
+
};
|
|
74
|
+
readonly 'server.update_available': {
|
|
75
|
+
readonly context: "server";
|
|
76
|
+
readonly group: "updates";
|
|
77
|
+
readonly variables: readonly ["server.name", "server.type", "installedVersion", "latestVersion", "releaseUrl"];
|
|
78
|
+
};
|
|
79
|
+
readonly 'tracearr.update_available': {
|
|
80
|
+
readonly context: "install";
|
|
81
|
+
readonly group: "updates";
|
|
82
|
+
readonly variables: readonly ["current", "latest", "releaseUrl"];
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
export type TriggerType = keyof typeof TRIGGERS;
|
|
86
|
+
export declare const TRIGGER_TYPES: TriggerType[];
|
|
87
|
+
/** Triggers a violation is never about: nobody did anything wrong by picking up a new phone. */
|
|
88
|
+
export declare const NOTIFICATION_ONLY_TRIGGERS: readonly ["account.new_device", "account.trust_changed"];
|
|
89
|
+
export declare const heldForParamsSchema: z.ZodObject<{
|
|
90
|
+
minutes: z.ZodNumber;
|
|
91
|
+
measure: z.ZodEnum<{
|
|
92
|
+
current: "current";
|
|
93
|
+
total: "total";
|
|
94
|
+
}>;
|
|
95
|
+
}, z.core.$strict>;
|
|
96
|
+
export declare const inactiveForParamsSchema: z.ZodObject<{
|
|
97
|
+
days: z.ZodNumber;
|
|
98
|
+
}, z.core.$strict>;
|
|
99
|
+
export declare const triggerNodeSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
100
|
+
type: z.ZodEnum<{
|
|
101
|
+
"session.started": "session.started";
|
|
102
|
+
"session.stopped": "session.stopped";
|
|
103
|
+
"session.transcode_changed": "session.transcode_changed";
|
|
104
|
+
"session.paused": "session.paused";
|
|
105
|
+
"account.new_device": "account.new_device";
|
|
106
|
+
"account.trust_changed": "account.trust_changed";
|
|
107
|
+
"media.added": "media.added";
|
|
108
|
+
"media.upgraded": "media.upgraded";
|
|
109
|
+
"server.down": "server.down";
|
|
110
|
+
"server.up": "server.up";
|
|
111
|
+
"plugin.update_available": "plugin.update_available";
|
|
112
|
+
"server.update_available": "server.update_available";
|
|
113
|
+
"tracearr.update_available": "tracearr.update_available";
|
|
114
|
+
}>;
|
|
115
|
+
id: z.ZodUUID;
|
|
116
|
+
enabled: z.ZodBoolean;
|
|
117
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
118
|
+
type: z.ZodLiteral<"session.held_for">;
|
|
119
|
+
params: z.ZodObject<{
|
|
120
|
+
minutes: z.ZodNumber;
|
|
121
|
+
measure: z.ZodEnum<{
|
|
122
|
+
current: "current";
|
|
123
|
+
total: "total";
|
|
124
|
+
}>;
|
|
125
|
+
}, z.core.$strict>;
|
|
126
|
+
id: z.ZodUUID;
|
|
127
|
+
enabled: z.ZodBoolean;
|
|
128
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
129
|
+
type: z.ZodLiteral<"account.inactive_for">;
|
|
130
|
+
params: z.ZodObject<{
|
|
131
|
+
days: z.ZodNumber;
|
|
132
|
+
}, z.core.$strict>;
|
|
133
|
+
id: z.ZodUUID;
|
|
134
|
+
enabled: z.ZodBoolean;
|
|
135
|
+
}, z.core.$strict>], "type">;
|
|
136
|
+
export type TriggerNode = z.infer<typeof triggerNodeSchema>;
|
|
137
|
+
/** The most demanding context every enabled trigger can satisfy; null when nothing is enabled. */
|
|
138
|
+
export declare function contextOf(triggers: readonly TriggerNode[]): TriggerContext | null;
|
|
139
|
+
/** The variables every enabled trigger offers, so a template renders whichever one fired. */
|
|
140
|
+
export declare function variablesFor(triggers: readonly TriggerNode[]): string[];
|
|
141
|
+
//# sourceMappingURL=triggers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"triggers.d.ts","sourceRoot":"","sources":["../../src/automations/triggers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAC;AAcpF,6EAA6E;AAC7E,wBAAgB,eAAe,CAAC,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,cAAc,GAAG,OAAO,CAK1F;AAmDD,6DAA6D;AAC7D,eAAO,MAAM,cAAc,oEAAqE,CAAC;AACjG,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3D,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6DpB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,MAAM,OAAO,QAAQ,CAAC;AAChD,eAAO,MAAM,aAAa,EAA4B,WAAW,EAAE,CAAC;AAEpE,gGAAgG;AAChG,eAAO,MAAM,0BAA0B,0DAGI,CAAC;AAa5C,eAAO,MAAM,mBAAmB;;;;;;kBAG9B,CAAC;AACH,eAAO,MAAM,uBAAuB;;kBAElC,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4BAQ5B,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D,kGAAkG;AAClG,wBAAgB,SAAS,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,GAAG,cAAc,GAAG,IAAI,CAQjF;AAED,6FAA6F;AAC7F,wBAAgB,YAAY,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,GAAG,MAAM,EAAE,CAOvE"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* What each context sits under. `media` names a server and no account, so the
|
|
4
|
+
* contexts are a tree rather than a line and `install` is its root.
|
|
5
|
+
*/
|
|
6
|
+
const TRIGGER_CONTEXT_PARENT = {
|
|
7
|
+
session: 'account',
|
|
8
|
+
account: 'server',
|
|
9
|
+
media: 'server',
|
|
10
|
+
server: 'install',
|
|
11
|
+
install: null,
|
|
12
|
+
};
|
|
13
|
+
/** Whether a trigger of this context carries everything `requires` names. */
|
|
14
|
+
export function contextSupplies(context, requires) {
|
|
15
|
+
for (let at = context; at; at = TRIGGER_CONTEXT_PARENT[at]) {
|
|
16
|
+
if (at === requires)
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
/** The narrowest context both supply: their lowest common ancestor in the tree. */
|
|
22
|
+
function meet(a, b) {
|
|
23
|
+
for (let at = b; at; at = TRIGGER_CONTEXT_PARENT[at]) {
|
|
24
|
+
if (contextSupplies(a, at))
|
|
25
|
+
return at;
|
|
26
|
+
}
|
|
27
|
+
// Unreachable: every chain ends at the root, which supplies nothing and is shared.
|
|
28
|
+
return 'install';
|
|
29
|
+
}
|
|
30
|
+
const SESSION_VARS = [
|
|
31
|
+
'user.username',
|
|
32
|
+
'user.identityName',
|
|
33
|
+
'session.mediaTitle',
|
|
34
|
+
'session.mediaType',
|
|
35
|
+
'server.name',
|
|
36
|
+
'server.type',
|
|
37
|
+
];
|
|
38
|
+
const ACCOUNT_VARS = ['user.username', 'user.identityName', 'server.name', 'server.type'];
|
|
39
|
+
const SERVER_VARS = ['server.name', 'server.type'];
|
|
40
|
+
/** `server.name` doubles `media.server` so an automation that also carries a server trigger keeps one. */
|
|
41
|
+
const MEDIA_VARS = [
|
|
42
|
+
'media.title',
|
|
43
|
+
'media.name',
|
|
44
|
+
'media.show',
|
|
45
|
+
'media.season',
|
|
46
|
+
'media.episode',
|
|
47
|
+
'media.episodeCount',
|
|
48
|
+
'media.type',
|
|
49
|
+
'media.year',
|
|
50
|
+
'media.library',
|
|
51
|
+
'media.server',
|
|
52
|
+
'server.name',
|
|
53
|
+
'server.type',
|
|
54
|
+
];
|
|
55
|
+
const MEDIA_QUALITY_VARS = [
|
|
56
|
+
'media.from.resolution',
|
|
57
|
+
'media.to.resolution',
|
|
58
|
+
'media.from.dynamicRange',
|
|
59
|
+
'media.to.dynamicRange',
|
|
60
|
+
'media.from.videoCodec',
|
|
61
|
+
'media.to.videoCodec',
|
|
62
|
+
'media.from.audioCodec',
|
|
63
|
+
'media.to.audioCodec',
|
|
64
|
+
'media.from.audioChannels',
|
|
65
|
+
'media.to.audioChannels',
|
|
66
|
+
'media.from.fileSize',
|
|
67
|
+
'media.to.fileSize',
|
|
68
|
+
];
|
|
69
|
+
/** What a trigger is about, and what the list filters on. */
|
|
70
|
+
export const TRIGGER_GROUPS = ['sessions', 'accounts', 'library', 'servers', 'updates'];
|
|
71
|
+
export const TRIGGERS = {
|
|
72
|
+
'session.started': { context: 'session', group: 'sessions', variables: SESSION_VARS },
|
|
73
|
+
'session.stopped': {
|
|
74
|
+
context: 'session',
|
|
75
|
+
group: 'sessions',
|
|
76
|
+
variables: [...SESSION_VARS, 'durationMinutes'],
|
|
77
|
+
},
|
|
78
|
+
'session.transcode_changed': { context: 'session', group: 'sessions', variables: SESSION_VARS },
|
|
79
|
+
'session.paused': { context: 'session', group: 'sessions', variables: SESSION_VARS },
|
|
80
|
+
'session.held_for': {
|
|
81
|
+
context: 'session',
|
|
82
|
+
group: 'sessions',
|
|
83
|
+
variables: [...SESSION_VARS, 'minutes'],
|
|
84
|
+
},
|
|
85
|
+
'account.inactive_for': {
|
|
86
|
+
context: 'account',
|
|
87
|
+
group: 'accounts',
|
|
88
|
+
variables: [...ACCOUNT_VARS, 'days'],
|
|
89
|
+
},
|
|
90
|
+
'account.new_device': {
|
|
91
|
+
context: 'session',
|
|
92
|
+
group: 'accounts',
|
|
93
|
+
variables: [
|
|
94
|
+
...SESSION_VARS,
|
|
95
|
+
'device.name',
|
|
96
|
+
'device.platform',
|
|
97
|
+
'device.product',
|
|
98
|
+
'device.location',
|
|
99
|
+
],
|
|
100
|
+
},
|
|
101
|
+
'account.trust_changed': {
|
|
102
|
+
context: 'account',
|
|
103
|
+
group: 'accounts',
|
|
104
|
+
variables: [...ACCOUNT_VARS, 'trust.previous', 'trust.new', 'trust.reason'],
|
|
105
|
+
},
|
|
106
|
+
'media.added': { context: 'media', group: 'library', variables: MEDIA_VARS },
|
|
107
|
+
'media.upgraded': {
|
|
108
|
+
context: 'media',
|
|
109
|
+
group: 'library',
|
|
110
|
+
variables: [...MEDIA_VARS, ...MEDIA_QUALITY_VARS],
|
|
111
|
+
},
|
|
112
|
+
'server.down': { context: 'server', group: 'servers', variables: SERVER_VARS },
|
|
113
|
+
'server.up': { context: 'server', group: 'servers', variables: SERVER_VARS },
|
|
114
|
+
'plugin.update_available': {
|
|
115
|
+
context: 'server',
|
|
116
|
+
group: 'updates',
|
|
117
|
+
variables: [...SERVER_VARS, 'installedVersion', 'latestVersion', 'downloadUrl'],
|
|
118
|
+
},
|
|
119
|
+
'server.update_available': {
|
|
120
|
+
context: 'server',
|
|
121
|
+
group: 'updates',
|
|
122
|
+
variables: [...SERVER_VARS, 'installedVersion', 'latestVersion', 'releaseUrl'],
|
|
123
|
+
},
|
|
124
|
+
'tracearr.update_available': {
|
|
125
|
+
context: 'install',
|
|
126
|
+
group: 'updates',
|
|
127
|
+
variables: ['current', 'latest', 'releaseUrl'],
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
export const TRIGGER_TYPES = Object.keys(TRIGGERS);
|
|
131
|
+
/** Triggers a violation is never about: nobody did anything wrong by picking up a new phone. */
|
|
132
|
+
export const NOTIFICATION_ONLY_TRIGGERS = [
|
|
133
|
+
'account.new_device',
|
|
134
|
+
'account.trust_changed',
|
|
135
|
+
];
|
|
136
|
+
const PARAMLESS_TRIGGER_TYPES = TRIGGER_TYPES.filter((type) => type !== 'session.held_for' && type !== 'account.inactive_for');
|
|
137
|
+
// z.uuid() rather than schemas.ts's uuidSchema: schemas.ts re-exports this directory's
|
|
138
|
+
// condition and action schemas, and importing back would read the binding before it exists.
|
|
139
|
+
const nodeBase = { id: z.uuid(), enabled: z.boolean() };
|
|
140
|
+
export const heldForParamsSchema = z.strictObject({
|
|
141
|
+
minutes: z.number().int().min(1).max(1440),
|
|
142
|
+
measure: z.enum(['current', 'total']),
|
|
143
|
+
});
|
|
144
|
+
export const inactiveForParamsSchema = z.strictObject({
|
|
145
|
+
days: z.number().int().min(1).max(3650),
|
|
146
|
+
});
|
|
147
|
+
export const triggerNodeSchema = z.discriminatedUnion('type', [
|
|
148
|
+
z.strictObject({ ...nodeBase, type: z.enum(PARAMLESS_TRIGGER_TYPES) }),
|
|
149
|
+
z.strictObject({ ...nodeBase, type: z.literal('session.held_for'), params: heldForParamsSchema }),
|
|
150
|
+
z.strictObject({
|
|
151
|
+
...nodeBase,
|
|
152
|
+
type: z.literal('account.inactive_for'),
|
|
153
|
+
params: inactiveForParamsSchema,
|
|
154
|
+
}),
|
|
155
|
+
]);
|
|
156
|
+
/** The most demanding context every enabled trigger can satisfy; null when nothing is enabled. */
|
|
157
|
+
export function contextOf(triggers) {
|
|
158
|
+
let shared = null;
|
|
159
|
+
for (const trigger of triggers) {
|
|
160
|
+
if (!trigger.enabled)
|
|
161
|
+
continue;
|
|
162
|
+
const context = TRIGGERS[trigger.type].context;
|
|
163
|
+
shared = shared === null ? context : meet(shared, context);
|
|
164
|
+
}
|
|
165
|
+
return shared;
|
|
166
|
+
}
|
|
167
|
+
/** The variables every enabled trigger offers, so a template renders whichever one fired. */
|
|
168
|
+
export function variablesFor(triggers) {
|
|
169
|
+
const sets = triggers
|
|
170
|
+
.filter((trigger) => trigger.enabled)
|
|
171
|
+
.map((trigger) => new Set(TRIGGERS[trigger.type].variables));
|
|
172
|
+
const first = sets[0];
|
|
173
|
+
if (!first)
|
|
174
|
+
return [];
|
|
175
|
+
return [...first].filter((variable) => sets.every((set) => set.has(variable)));
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=triggers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"triggers.js","sourceRoot":"","sources":["../../src/automations/triggers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB;;;GAGG;AACH,MAAM,sBAAsB,GAAkD;IAC5E,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,QAAQ;IACjB,KAAK,EAAE,QAAQ;IACf,MAAM,EAAE,SAAS;IACjB,OAAO,EAAE,IAAI;CACd,CAAC;AAEF,6EAA6E;AAC7E,MAAM,UAAU,eAAe,CAAC,OAAuB,EAAE,QAAwB;IAC/E,KAAK,IAAI,EAAE,GAA0B,OAAO,EAAE,EAAE,EAAE,EAAE,GAAG,sBAAsB,CAAC,EAAE,CAAC,EAAE,CAAC;QAClF,IAAI,EAAE,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;IACnC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,mFAAmF;AACnF,SAAS,IAAI,CAAC,CAAiB,EAAE,CAAiB;IAChD,KAAK,IAAI,EAAE,GAA0B,CAAC,EAAE,EAAE,EAAE,EAAE,GAAG,sBAAsB,CAAC,EAAE,CAAC,EAAE,CAAC;QAC5E,IAAI,eAAe,CAAC,CAAC,EAAE,EAAE,CAAC;YAAE,OAAO,EAAE,CAAC;IACxC,CAAC;IACD,mFAAmF;IACnF,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,YAAY,GAAG;IACnB,eAAe;IACf,mBAAmB;IACnB,oBAAoB;IACpB,mBAAmB;IACnB,aAAa;IACb,aAAa;CACL,CAAC;AACX,MAAM,YAAY,GAAG,CAAC,eAAe,EAAE,mBAAmB,EAAE,aAAa,EAAE,aAAa,CAAU,CAAC;AACnG,MAAM,WAAW,GAAG,CAAC,aAAa,EAAE,aAAa,CAAU,CAAC;AAC5D,0GAA0G;AAC1G,MAAM,UAAU,GAAG;IACjB,aAAa;IACb,YAAY;IACZ,YAAY;IACZ,cAAc;IACd,eAAe;IACf,oBAAoB;IACpB,YAAY;IACZ,YAAY;IACZ,eAAe;IACf,cAAc;IACd,aAAa;IACb,aAAa;CACL,CAAC;AACX,MAAM,kBAAkB,GAAG;IACzB,uBAAuB;IACvB,qBAAqB;IACrB,yBAAyB;IACzB,uBAAuB;IACvB,uBAAuB;IACvB,qBAAqB;IACrB,uBAAuB;IACvB,qBAAqB;IACrB,0BAA0B;IAC1B,wBAAwB;IACxB,qBAAqB;IACrB,mBAAmB;CACX,CAAC;AAEX,6DAA6D;AAC7D,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,CAAU,CAAC;AAGjG,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,iBAAiB,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE;IACrF,iBAAiB,EAAE;QACjB,OAAO,EAAE,SAAS;QAClB,KAAK,EAAE,UAAU;QACjB,SAAS,EAAE,CAAC,GAAG,YAAY,EAAE,iBAAiB,CAAC;KAChD;IACD,2BAA2B,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE;IAC/F,gBAAgB,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE;IACpF,kBAAkB,EAAE;QAClB,OAAO,EAAE,SAAS;QAClB,KAAK,EAAE,UAAU;QACjB,SAAS,EAAE,CAAC,GAAG,YAAY,EAAE,SAAS,CAAC;KACxC;IACD,sBAAsB,EAAE;QACtB,OAAO,EAAE,SAAS;QAClB,KAAK,EAAE,UAAU;QACjB,SAAS,EAAE,CAAC,GAAG,YAAY,EAAE,MAAM,CAAC;KACrC;IACD,oBAAoB,EAAE;QACpB,OAAO,EAAE,SAAS;QAClB,KAAK,EAAE,UAAU;QACjB,SAAS,EAAE;YACT,GAAG,YAAY;YACf,aAAa;YACb,iBAAiB;YACjB,gBAAgB;YAChB,iBAAiB;SAClB;KACF;IACD,uBAAuB,EAAE;QACvB,OAAO,EAAE,SAAS;QAClB,KAAK,EAAE,UAAU;QACjB,SAAS,EAAE,CAAC,GAAG,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,cAAc,CAAC;KAC5E;IACD,aAAa,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE;IAC5E,gBAAgB,EAAE;QAChB,OAAO,EAAE,OAAO;QAChB,KAAK,EAAE,SAAS;QAChB,SAAS,EAAE,CAAC,GAAG,UAAU,EAAE,GAAG,kBAAkB,CAAC;KAClD;IACD,aAAa,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE;IAC9E,WAAW,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE;IAC5E,yBAAyB,EAAE;QACzB,OAAO,EAAE,QAAQ;QACjB,KAAK,EAAE,SAAS;QAChB,SAAS,EAAE,CAAC,GAAG,WAAW,EAAE,kBAAkB,EAAE,eAAe,EAAE,aAAa,CAAC;KAChF;IACD,yBAAyB,EAAE;QACzB,OAAO,EAAE,QAAQ;QACjB,KAAK,EAAE,SAAS;QAChB,SAAS,EAAE,CAAC,GAAG,WAAW,EAAE,kBAAkB,EAAE,eAAe,EAAE,YAAY,CAAC;KAC/E;IACD,2BAA2B,EAAE;QAC3B,OAAO,EAAE,SAAS;QAClB,KAAK,EAAE,SAAS;QAChB,SAAS,EAAE,CAAC,SAAS,EAAE,QAAQ,EAAE,YAAY,CAAC;KAC/C;CAIF,CAAC;AAGF,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAkB,CAAC;AAEpE,gGAAgG;AAChG,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,oBAAoB;IACpB,uBAAuB;CACkB,CAAC;AAI5C,MAAM,uBAAuB,GAAG,aAAa,CAAC,MAAM,CAClD,CAAC,IAAI,EAAgC,EAAE,CACrC,IAAI,KAAK,kBAAkB,IAAI,IAAI,KAAK,sBAAsB,CACjE,CAAC;AAEF,uFAAuF;AACvF,4FAA4F;AAC5F,MAAM,QAAQ,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;AAExD,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,YAAY,CAAC;IAChD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;IAC1C,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;CACtC,CAAC,CAAC;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,YAAY,CAAC;IACpD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;CACxC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,kBAAkB,CAAC,MAAM,EAAE;IAC5D,CAAC,CAAC,YAAY,CAAC,EAAE,GAAG,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,EAAE,CAAC;IACtE,CAAC,CAAC,YAAY,CAAC,EAAE,GAAG,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,kBAAkB,CAAC,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;IACjG,CAAC,CAAC,YAAY,CAAC;QACb,GAAG,QAAQ;QACX,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,sBAAsB,CAAC;QACvC,MAAM,EAAE,uBAAuB;KAChC,CAAC;CACH,CAAC,CAAC;AAGH,kGAAkG;AAClG,MAAM,UAAU,SAAS,CAAC,QAAgC;IACxD,IAAI,MAAM,GAA0B,IAAI,CAAC;IACzC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,CAAC,OAAO,CAAC,OAAO;YAAE,SAAS;QAC/B,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC;QAC/C,MAAM,GAAG,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7D,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,6FAA6F;AAC7F,MAAM,UAAU,YAAY,CAAC,QAAgC;IAC3D,MAAM,IAAI,GAAG,QAAQ;SAClB,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC;SACpC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,GAAG,CAAS,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IACvE,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACtB,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACjF,CAAC"}
|
package/dist/constants.d.ts
CHANGED
|
@@ -2,45 +2,7 @@
|
|
|
2
2
|
* Shared constants for Tracearr
|
|
3
3
|
*/
|
|
4
4
|
import { classifyByDimensions, type ResolutionLabel } from './resolution.js';
|
|
5
|
-
export
|
|
6
|
-
readonly impossible_travel: {
|
|
7
|
-
readonly maxSpeedKmh: 500;
|
|
8
|
-
readonly ignoreVpnRanges: false;
|
|
9
|
-
readonly excludePrivateIps: false;
|
|
10
|
-
};
|
|
11
|
-
readonly simultaneous_locations: {
|
|
12
|
-
readonly minDistanceKm: 100;
|
|
13
|
-
readonly excludePrivateIps: false;
|
|
14
|
-
};
|
|
15
|
-
readonly device_velocity: {
|
|
16
|
-
readonly maxIps: 5;
|
|
17
|
-
readonly windowHours: 24;
|
|
18
|
-
readonly excludePrivateIps: false;
|
|
19
|
-
readonly groupByDevice: false;
|
|
20
|
-
};
|
|
21
|
-
readonly concurrent_streams: {
|
|
22
|
-
readonly maxStreams: 3;
|
|
23
|
-
readonly excludePrivateIps: false;
|
|
24
|
-
};
|
|
25
|
-
readonly geo_restriction: {
|
|
26
|
-
readonly mode: "blocklist";
|
|
27
|
-
readonly countries: readonly [];
|
|
28
|
-
readonly excludePrivateIps: false;
|
|
29
|
-
};
|
|
30
|
-
readonly account_inactivity: {
|
|
31
|
-
readonly inactivityValue: 30;
|
|
32
|
-
readonly inactivityUnit: "days";
|
|
33
|
-
};
|
|
34
|
-
};
|
|
35
|
-
export declare const RULE_DISPLAY_NAMES: {
|
|
36
|
-
readonly impossible_travel: "Impossible Travel";
|
|
37
|
-
readonly simultaneous_locations: "Simultaneous Locations";
|
|
38
|
-
readonly device_velocity: "Device Velocity";
|
|
39
|
-
readonly concurrent_streams: "Concurrent Streams";
|
|
40
|
-
readonly geo_restriction: "Geo Restriction";
|
|
41
|
-
readonly account_inactivity: "Account Inactivity";
|
|
42
|
-
};
|
|
43
|
-
export declare const IDENTITY_AWARE_CONDITION_FIELDS: readonly ["concurrent_streams", "active_session_distance_km", "travel_speed_kmh", "unique_ips_in_window", "unique_devices_in_window"];
|
|
5
|
+
export { IDENTITY_AWARE_CONDITION_FIELDS } from './automations/conditions.js';
|
|
44
6
|
export declare const SEVERITY_LEVELS: {
|
|
45
7
|
readonly low: {
|
|
46
8
|
readonly label: "Low";
|
|
@@ -62,6 +24,7 @@ export declare const WS_EVENTS: {
|
|
|
62
24
|
readonly SESSION_STOPPED: "session:stopped";
|
|
63
25
|
readonly SESSION_UPDATED: "session:updated";
|
|
64
26
|
readonly VIOLATION_NEW: "violation:new";
|
|
27
|
+
readonly RUN_FINISHED: "run:finished";
|
|
65
28
|
readonly STATS_UPDATED: "stats:updated";
|
|
66
29
|
readonly IMPORT_PROGRESS: "import:progress";
|
|
67
30
|
readonly IMPORT_JELLYSTAT_PROGRESS: "import:jellystat:progress";
|
|
@@ -79,6 +42,7 @@ export declare const WS_EVENTS: {
|
|
|
79
42
|
readonly SERVER_CONNECTION: "server:connection";
|
|
80
43
|
readonly NOTIFICATION_TOAST: "notification:toast";
|
|
81
44
|
readonly DESTINATIONS_CHANGED: "destinations:changed";
|
|
45
|
+
readonly SERVERS_CHANGED: "servers:changed";
|
|
82
46
|
};
|
|
83
47
|
/**
|
|
84
48
|
* Set the global prefix prepended to all Redis keys.
|
|
@@ -144,6 +108,9 @@ export declare const REDIS_KEYS: {
|
|
|
144
108
|
LIBRARY_SYNC_SHORTFALL: (serverId: string, libraryId: string) => string;
|
|
145
109
|
LIBRARY_PRECACHE_WATERMARK: (serverId: string) => string;
|
|
146
110
|
LIBRARY_PRECACHE_LAST_FULL: (serverId: string) => string;
|
|
111
|
+
IMAGE_CACHE_SCHEMA: string;
|
|
112
|
+
IMAGE_CACHE_TALLY: string;
|
|
113
|
+
IMAGE_CACHE_DISK_LIMITED: string;
|
|
147
114
|
REFRESH_TOKEN: (hash: string) => string;
|
|
148
115
|
PLEX_TEMP_TOKEN: (token: string) => string;
|
|
149
116
|
MOBILE_REFRESH_TOKEN: (hash: string) => string;
|
|
@@ -154,7 +121,9 @@ export declare const REDIS_KEYS: {
|
|
|
154
121
|
SESSION_LOCK: (serverId: string, sessionKey: string) => string;
|
|
155
122
|
TERMINATION_COOLDOWN: (serverId: string, sessionKey: string, ratingKey: string) => string;
|
|
156
123
|
TERMINATION_COOLDOWN_COMPOSITE: (serverId: string, serverUserId: string, deviceId: string, ratingKey: string) => string;
|
|
157
|
-
|
|
124
|
+
ACTION_COOLDOWN: (automationId: string, targetId: string) => string;
|
|
125
|
+
AUTOMATION_COOLDOWN: (automationId: string, subjectKey: string) => string;
|
|
126
|
+
AUTOMATION_EVALS: (automationId: string) => string;
|
|
158
127
|
SESSION_WRITE_RETRY: (sessionId: string) => string;
|
|
159
128
|
readonly SESSION_WRITE_RETRY_SET: string;
|
|
160
129
|
FILTER_OPTIONS: (userId: string, scopeHash: string) => string;
|
|
@@ -204,6 +173,17 @@ export declare const NOTIFICATION_EVENTS: {
|
|
|
204
173
|
readonly SERVER_DOWN: "server_down";
|
|
205
174
|
readonly SERVER_UP: "server_up";
|
|
206
175
|
readonly PLUGIN_UPDATE_AVAILABLE: "plugin_update_available";
|
|
176
|
+
readonly SERVER_UPDATE_AVAILABLE: "server_update_available";
|
|
177
|
+
readonly TRACEARR_UPDATE_AVAILABLE: "tracearr_update_available";
|
|
178
|
+
readonly MEDIA_ADDED: "media_added";
|
|
179
|
+
readonly MEDIA_UPGRADED: "media_upgraded";
|
|
180
|
+
readonly NEW_DEVICE: "new_device";
|
|
181
|
+
readonly TRUST_SCORE_CHANGED: "trust_score_changed";
|
|
182
|
+
};
|
|
183
|
+
/** The one size a poster is cached at. Every poster URL the server hands out uses it. */
|
|
184
|
+
export declare const POSTER_IMAGE_SIZE: {
|
|
185
|
+
readonly width: 360;
|
|
186
|
+
readonly height: 540;
|
|
207
187
|
};
|
|
208
188
|
/**
|
|
209
189
|
* server_version_key of the placeholder version rows the multi-version
|
|
@@ -274,6 +254,8 @@ export declare const UNIT_CONVERSION: {
|
|
|
274
254
|
readonly KM_TO_MILES: 0.621371;
|
|
275
255
|
readonly MILES_TO_KM: 1.60934;
|
|
276
256
|
};
|
|
257
|
+
/** Base 1024, matching the byte formatter the dashboard renders file sizes with. */
|
|
258
|
+
export declare const BYTES_PER_GB: number;
|
|
277
259
|
export type UnitSystem = 'metric' | 'imperial';
|
|
278
260
|
/**
|
|
279
261
|
* Convert kilometers to miles
|
package/dist/constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,oBAAoB,EAAE,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"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"}
|
package/dist/constants.js
CHANGED
|
@@ -2,60 +2,7 @@
|
|
|
2
2
|
* Shared constants for Tracearr
|
|
3
3
|
*/
|
|
4
4
|
import { classifyByDimensions } from './resolution.js';
|
|
5
|
-
|
|
6
|
-
export const RULE_DEFAULTS = {
|
|
7
|
-
impossible_travel: {
|
|
8
|
-
maxSpeedKmh: 500,
|
|
9
|
-
ignoreVpnRanges: false,
|
|
10
|
-
excludePrivateIps: false,
|
|
11
|
-
},
|
|
12
|
-
simultaneous_locations: {
|
|
13
|
-
minDistanceKm: 100,
|
|
14
|
-
excludePrivateIps: false,
|
|
15
|
-
},
|
|
16
|
-
device_velocity: {
|
|
17
|
-
maxIps: 5,
|
|
18
|
-
windowHours: 24,
|
|
19
|
-
excludePrivateIps: false,
|
|
20
|
-
groupByDevice: false,
|
|
21
|
-
},
|
|
22
|
-
concurrent_streams: {
|
|
23
|
-
maxStreams: 3,
|
|
24
|
-
excludePrivateIps: false,
|
|
25
|
-
},
|
|
26
|
-
geo_restriction: {
|
|
27
|
-
mode: 'blocklist',
|
|
28
|
-
countries: [],
|
|
29
|
-
excludePrivateIps: false,
|
|
30
|
-
},
|
|
31
|
-
account_inactivity: {
|
|
32
|
-
inactivityValue: 30,
|
|
33
|
-
inactivityUnit: 'days',
|
|
34
|
-
},
|
|
35
|
-
};
|
|
36
|
-
// Rule type display names
|
|
37
|
-
export const RULE_DISPLAY_NAMES = {
|
|
38
|
-
impossible_travel: 'Impossible Travel',
|
|
39
|
-
simultaneous_locations: 'Simultaneous Locations',
|
|
40
|
-
device_velocity: 'Device Velocity',
|
|
41
|
-
concurrent_streams: 'Concurrent Streams',
|
|
42
|
-
geo_restriction: 'Geo Restriction',
|
|
43
|
-
account_inactivity: 'Account Inactivity',
|
|
44
|
-
};
|
|
45
|
-
// Condition fields whose evaluators are identity-aware (see belongsToIdentity in
|
|
46
|
-
// services/rules/evaluators/index.ts): they aggregate across every server_user id
|
|
47
|
-
// belonging to the same identity when the evaluation context carries
|
|
48
|
-
// identityServerUserIds. The UI (RuleBuilder) offers enforceAcrossServers as soon
|
|
49
|
-
// as ANY condition on the rule uses a field from this set, not only when every
|
|
50
|
-
// field does - one identity-aware condition is enough for cross-server action
|
|
51
|
-
// reach to make sense for the rule as a whole.
|
|
52
|
-
export const IDENTITY_AWARE_CONDITION_FIELDS = [
|
|
53
|
-
'concurrent_streams',
|
|
54
|
-
'active_session_distance_km',
|
|
55
|
-
'travel_speed_kmh',
|
|
56
|
-
'unique_ips_in_window',
|
|
57
|
-
'unique_devices_in_window',
|
|
58
|
-
];
|
|
5
|
+
export { IDENTITY_AWARE_CONDITION_FIELDS } from './automations/conditions.js';
|
|
59
6
|
// Severity levels
|
|
60
7
|
export const SEVERITY_LEVELS = {
|
|
61
8
|
low: { label: 'Low', priority: 1 },
|
|
@@ -72,6 +19,7 @@ export const WS_EVENTS = {
|
|
|
72
19
|
SESSION_STOPPED: 'session:stopped',
|
|
73
20
|
SESSION_UPDATED: 'session:updated',
|
|
74
21
|
VIOLATION_NEW: 'violation:new',
|
|
22
|
+
RUN_FINISHED: 'run:finished',
|
|
75
23
|
STATS_UPDATED: 'stats:updated',
|
|
76
24
|
IMPORT_PROGRESS: 'import:progress',
|
|
77
25
|
IMPORT_JELLYSTAT_PROGRESS: 'import:jellystat:progress',
|
|
@@ -89,6 +37,7 @@ export const WS_EVENTS = {
|
|
|
89
37
|
SERVER_CONNECTION: 'server:connection',
|
|
90
38
|
NOTIFICATION_TOAST: 'notification:toast',
|
|
91
39
|
DESTINATIONS_CHANGED: 'destinations:changed',
|
|
40
|
+
SERVERS_CHANGED: 'servers:changed',
|
|
92
41
|
};
|
|
93
42
|
// Redis key prefix (set at startup via setRedisPrefix)
|
|
94
43
|
let _redisPrefix = '';
|
|
@@ -245,6 +194,11 @@ export const REDIS_KEYS = {
|
|
|
245
194
|
// job walks library_items scoped only by server)
|
|
246
195
|
LIBRARY_PRECACHE_WATERMARK: (serverId) => `${_redisPrefix}tracearr:library:precache:watermark:${serverId}`,
|
|
247
196
|
LIBRARY_PRECACHE_LAST_FULL: (serverId) => `${_redisPrefix}tracearr:library:precache:last-full:${serverId}`,
|
|
197
|
+
// Poster cache: one-time boot reconciliation marker, the last sweep's tally,
|
|
198
|
+
// and the disk-limited flag the precache sets when the guard refused writes.
|
|
199
|
+
IMAGE_CACHE_SCHEMA: `${_redisPrefix}tracearr:image-cache:schema`,
|
|
200
|
+
IMAGE_CACHE_TALLY: `${_redisPrefix}tracearr:image-cache:tally`,
|
|
201
|
+
IMAGE_CACHE_DISK_LIMITED: `${_redisPrefix}tracearr:image-cache:disk-limited`,
|
|
248
202
|
// Auth tokens
|
|
249
203
|
REFRESH_TOKEN: (hash) => `${_redisPrefix}tracearr:refresh:${hash}`,
|
|
250
204
|
PLEX_TEMP_TOKEN: (token) => `${_redisPrefix}tracearr:plex_temp:${token}`,
|
|
@@ -260,8 +214,13 @@ export const REDIS_KEYS = {
|
|
|
260
214
|
SESSION_LOCK: (serverId, sessionKey) => `${_redisPrefix}session:lock:${serverId}:${sessionKey}`,
|
|
261
215
|
TERMINATION_COOLDOWN: (serverId, sessionKey, ratingKey) => `${_redisPrefix}termination:cooldown:${serverId}:${sessionKey}:${ratingKey}`,
|
|
262
216
|
TERMINATION_COOLDOWN_COMPOSITE: (serverId, serverUserId, deviceId, ratingKey) => `${_redisPrefix}termination:cooldown:composite:${serverId}:${serverUserId}:${deviceId}:${ratingKey}`,
|
|
263
|
-
//
|
|
264
|
-
|
|
217
|
+
// Per-action cooldown on one target. The key string keeps its v1 shape so
|
|
218
|
+
// cooldowns already armed in Redis stay honoured.
|
|
219
|
+
ACTION_COOLDOWN: (automationId, targetId) => `${_redisPrefix}tracearr:rule:cooldown:${automationId}:${targetId}`,
|
|
220
|
+
// Automation-level cooldown, keyed on the run's subject
|
|
221
|
+
AUTOMATION_COOLDOWN: (automationId, subjectKey) => `${_redisPrefix}tracearr:automation:cooldown:${automationId}:${subjectKey}`,
|
|
222
|
+
// Capped ring of evaluations that matched a trigger but recorded no run
|
|
223
|
+
AUTOMATION_EVALS: (automationId) => `${_redisPrefix}tracearr:automation:evals:${automationId}`,
|
|
265
224
|
// Session write retry queue (for failed DB writes)
|
|
266
225
|
SESSION_WRITE_RETRY: (sessionId) => `${_redisPrefix}tracearr:session:write-retry:${sessionId}`,
|
|
267
226
|
get SESSION_WRITE_RETRY_SET() {
|
|
@@ -327,7 +286,15 @@ export const NOTIFICATION_EVENTS = {
|
|
|
327
286
|
SERVER_DOWN: 'server_down',
|
|
328
287
|
SERVER_UP: 'server_up',
|
|
329
288
|
PLUGIN_UPDATE_AVAILABLE: 'plugin_update_available',
|
|
289
|
+
SERVER_UPDATE_AVAILABLE: 'server_update_available',
|
|
290
|
+
TRACEARR_UPDATE_AVAILABLE: 'tracearr_update_available',
|
|
291
|
+
MEDIA_ADDED: 'media_added',
|
|
292
|
+
MEDIA_UPGRADED: 'media_upgraded',
|
|
293
|
+
NEW_DEVICE: 'new_device',
|
|
294
|
+
TRUST_SCORE_CHANGED: 'trust_score_changed',
|
|
330
295
|
};
|
|
296
|
+
/** The one size a poster is cached at. Every poster URL the server hands out uses it. */
|
|
297
|
+
export const POSTER_IMAGE_SIZE = { width: 360, height: 540 };
|
|
331
298
|
// API version
|
|
332
299
|
/**
|
|
333
300
|
* server_version_key of the placeholder version rows the multi-version
|
|
@@ -417,6 +384,8 @@ export const UNIT_CONVERSION = {
|
|
|
417
384
|
KM_TO_MILES: 0.621371,
|
|
418
385
|
MILES_TO_KM: 1.60934,
|
|
419
386
|
};
|
|
387
|
+
/** Base 1024, matching the byte formatter the dashboard renders file sizes with. */
|
|
388
|
+
export const BYTES_PER_GB = 1024 ** 3;
|
|
420
389
|
/**
|
|
421
390
|
* Convert kilometers to miles
|
|
422
391
|
*/
|