@open-loyalty/mcp-server 1.3.6 → 1.4.1

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.
Files changed (42) hide show
  1. package/dist/instructions.d.ts +1 -1
  2. package/dist/instructions.js +18 -5
  3. package/dist/tools/achievement/index.js +10 -10
  4. package/dist/tools/achievement/schemas.js +16 -8
  5. package/dist/tools/reward/handlers.d.ts +3 -3
  6. package/dist/tools/reward/handlers.js +54 -8
  7. package/dist/tools/reward/index.d.ts +4 -8
  8. package/dist/tools/reward/index.js +13 -5
  9. package/dist/tools/reward/schemas.d.ts +3 -7
  10. package/dist/tools/reward/schemas.js +16 -8
  11. package/dist/tools/tierset.d.ts +1 -1
  12. package/dist/tools/tierset.js +49 -25
  13. package/dist/tools/transaction.js +5 -2
  14. package/dist/tools/wallet-type.js +27 -16
  15. package/dist/types/schemas/admin.d.ts +6 -6
  16. package/dist/types/schemas/role.d.ts +4 -4
  17. package/dist/types/schemas/wallet-type.js +7 -5
  18. package/package.json +1 -1
  19. package/dist/prompts/fan-engagement-setup.d.ts +0 -107
  20. package/dist/prompts/fan-engagement-setup.js +0 -492
  21. package/dist/tools/achievement.d.ts +0 -1017
  22. package/dist/tools/achievement.js +0 -354
  23. package/dist/tools/campaign.d.ts +0 -1800
  24. package/dist/tools/campaign.js +0 -737
  25. package/dist/tools/member.d.ts +0 -366
  26. package/dist/tools/member.js +0 -352
  27. package/dist/tools/reward.d.ts +0 -279
  28. package/dist/tools/reward.js +0 -361
  29. package/dist/tools/segment.d.ts +0 -816
  30. package/dist/tools/segment.js +0 -333
  31. package/dist/workflows/app-login-streak.d.ts +0 -39
  32. package/dist/workflows/app-login-streak.js +0 -298
  33. package/dist/workflows/early-arrival.d.ts +0 -33
  34. package/dist/workflows/early-arrival.js +0 -148
  35. package/dist/workflows/index.d.ts +0 -101
  36. package/dist/workflows/index.js +0 -208
  37. package/dist/workflows/match-attendance.d.ts +0 -45
  38. package/dist/workflows/match-attendance.js +0 -308
  39. package/dist/workflows/sportsbar-visit.d.ts +0 -41
  40. package/dist/workflows/sportsbar-visit.js +0 -284
  41. package/dist/workflows/vod-watching.d.ts +0 -43
  42. package/dist/workflows/vod-watching.js +0 -326
@@ -1,308 +0,0 @@
1
- /**
2
- * Match Attendance Workflow
3
- *
4
- * Creates a complete match attendance reward program including:
5
- * - Base campaign for per-match coin rewards
6
- * - Achievements for attendance milestones (6, 12 matches, etc.)
7
- * - Bonus campaigns triggered by achievement completion
8
- */
9
- import { campaignCreate, campaignList } from "../tools/campaign/handlers.js";
10
- import { achievementCreate, achievementList } from "../tools/achievement.js";
11
- import { badgeList } from "../tools/badge.js";
12
- import { formatOLDate, DEFAULTS } from "../prompts/fan-engagement-setup.js";
13
- // ============================================================================
14
- // Workflow Implementation
15
- // ============================================================================
16
- /**
17
- * Execute the match attendance workflow
18
- */
19
- export async function executeMatchAttendanceWorkflow(config = {}) {
20
- const result = {
21
- success: false,
22
- achievements: [],
23
- errors: [],
24
- summary: "",
25
- };
26
- // Merge with defaults
27
- const cfg = {
28
- coinsPerMatch: config.coinsPerMatch ?? DEFAULTS.matchAttendance.coinsPerMatch,
29
- milestones: config.milestones ?? DEFAULTS.matchAttendance.milestones,
30
- badgeNames: config.badgeNames ?? Object.values(DEFAULTS.matchAttendance.badges),
31
- milestoneBonuses: config.milestoneBonuses ?? Object.values(DEFAULTS.matchAttendance.milestoneBonuses),
32
- limitPerDay: config.limitPerDay ?? DEFAULTS.matchAttendance.limitPerDay,
33
- seasonStart: config.seasonStart ?? DEFAULTS.seasonDates.start,
34
- seasonEnd: config.seasonEnd ?? DEFAULTS.seasonDates.end,
35
- };
36
- try {
37
- // Step 1: Create base match attendance campaign
38
- const baseCampaignResult = await createBaseCampaign(cfg);
39
- if (baseCampaignResult.error) {
40
- result.errors.push(baseCampaignResult.error);
41
- }
42
- else {
43
- result.baseCampaignId = baseCampaignResult.campaignId;
44
- }
45
- // Step 2: Get available badges for achievements
46
- const badges = await getAvailableBadges();
47
- // Step 3: Create achievements and bonus campaigns for each milestone
48
- for (let i = 0; i < cfg.milestones.length; i++) {
49
- const milestone = cfg.milestones[i];
50
- const badgeName = cfg.badgeNames[i] || `Milestone ${milestone}`;
51
- const bonus = cfg.milestoneBonuses[i] || 500;
52
- const achievementResult = await createMilestoneAchievement(milestone, badgeName, badges, cfg.seasonStart, cfg.seasonEnd);
53
- if (achievementResult.error) {
54
- result.errors.push(achievementResult.error);
55
- continue;
56
- }
57
- const achievementEntry = {
58
- achievementId: achievementResult.achievementId,
59
- milestone,
60
- badgeName,
61
- };
62
- // Create bonus campaign for this achievement
63
- if (achievementResult.achievementId) {
64
- const bonusCampaignResult = await createAchievementBonusCampaign(achievementResult.achievementId, milestone, bonus, cfg.seasonStart, cfg.seasonEnd);
65
- if (bonusCampaignResult.error) {
66
- result.errors.push(bonusCampaignResult.error);
67
- }
68
- else {
69
- achievementEntry.bonusCampaignId = bonusCampaignResult.campaignId;
70
- }
71
- }
72
- result.achievements.push(achievementEntry);
73
- }
74
- // Step 4: Verify setup
75
- const verification = await verifySetup(result);
76
- if (verification.warnings.length > 0) {
77
- result.errors.push(...verification.warnings);
78
- }
79
- // Build summary
80
- result.success = result.baseCampaignId !== undefined && result.errors.length === 0;
81
- result.summary = buildSummary(cfg, result);
82
- }
83
- catch (error) {
84
- result.errors.push(`Workflow error: ${error instanceof Error ? error.message : String(error)}`);
85
- }
86
- return result;
87
- }
88
- // ============================================================================
89
- // Helper Functions
90
- // ============================================================================
91
- async function createBaseCampaign(cfg) {
92
- try {
93
- const response = await campaignCreate({
94
- type: "direct",
95
- trigger: "custom_event",
96
- event: "match_attendance",
97
- translations: {
98
- en: {
99
- name: "Match Attendance Reward",
100
- description: `Earn ${cfg.coinsPerMatch} coins for each match you attend`,
101
- },
102
- },
103
- activity: {
104
- startsAt: formatOLDate(cfg.seasonStart),
105
- endsAt: formatOLDate(cfg.seasonEnd),
106
- },
107
- rules: [
108
- {
109
- name: "Award coins for match attendance",
110
- effects: [
111
- {
112
- effect: "give_points",
113
- pointsRule: { fixedValue: cfg.coinsPerMatch },
114
- },
115
- ],
116
- },
117
- ],
118
- limits: {
119
- executionsPerMember: {
120
- value: cfg.limitPerDay,
121
- interval: { type: "days", value: 1 },
122
- },
123
- },
124
- active: true,
125
- });
126
- return { campaignId: response.campaignId };
127
- }
128
- catch (error) {
129
- return {
130
- error: `Failed to create base campaign: ${error instanceof Error ? error.message : String(error)}`,
131
- };
132
- }
133
- }
134
- async function getAvailableBadges() {
135
- try {
136
- const response = await badgeList({});
137
- const badgeMap = new Map();
138
- for (const badge of response.badges) {
139
- if (badge.name && badge.badgeTypeId) {
140
- badgeMap.set(badge.name.toLowerCase(), badge.badgeTypeId);
141
- }
142
- }
143
- return badgeMap;
144
- }
145
- catch {
146
- // Return empty map if badges can't be fetched - achievements will be created without badges
147
- return new Map();
148
- }
149
- }
150
- async function createMilestoneAchievement(milestone, badgeName, badges, seasonStart, seasonEnd) {
151
- try {
152
- // Find badge ID by name (case-insensitive)
153
- const badgeTypeId = badges.get(badgeName.toLowerCase());
154
- // Determine the goal value (for percentage, calculate based on assumed total matches)
155
- let periodGoal;
156
- let achievementName;
157
- let achievementDescription;
158
- if (typeof milestone === "string" && milestone.includes("%")) {
159
- // Percentage milestone (e.g., "80%")
160
- const percentage = parseInt(milestone.replace("%", ""), 10);
161
- // Assume ~19 home matches per season (typical for major football leagues)
162
- periodGoal = Math.ceil(19 * (percentage / 100));
163
- achievementName = `${milestone} Match Attendance`;
164
- achievementDescription = `Attend ${milestone} of all home matches this season`;
165
- }
166
- else {
167
- periodGoal = typeof milestone === "number" ? milestone : parseInt(milestone, 10);
168
- achievementName = `Attend ${periodGoal} Matches`;
169
- achievementDescription = `Be at ${periodGoal} home games this season`;
170
- }
171
- const achievementPayload = {
172
- translations: {
173
- en: {
174
- name: achievementName,
175
- description: achievementDescription,
176
- },
177
- },
178
- active: true,
179
- activity: {
180
- startsAt: formatOLDate(seasonStart),
181
- endsAt: formatOLDate(seasonEnd),
182
- },
183
- rules: [
184
- {
185
- trigger: "custom_event",
186
- event: "match_attendance",
187
- completeRule: {
188
- periodGoal,
189
- },
190
- },
191
- ],
192
- };
193
- // Add badge if found
194
- if (badgeTypeId) {
195
- achievementPayload.badgeTypeId = badgeTypeId;
196
- }
197
- const response = await achievementCreate(achievementPayload);
198
- return { achievementId: response.achievementId };
199
- }
200
- catch (error) {
201
- return {
202
- error: `Failed to create achievement for ${milestone}: ${error instanceof Error ? error.message : String(error)}`,
203
- };
204
- }
205
- }
206
- async function createAchievementBonusCampaign(achievementId, milestone, bonusCoins, seasonStart, seasonEnd) {
207
- try {
208
- const milestoneLabel = typeof milestone === "string" ? milestone : `${milestone} Matches`;
209
- const response = await campaignCreate({
210
- type: "direct",
211
- trigger: "achievement",
212
- translations: {
213
- en: {
214
- name: `${milestoneLabel} Achievement Bonus`,
215
- description: `Bonus ${bonusCoins} coins for completing the ${milestoneLabel} achievement`,
216
- },
217
- },
218
- activity: {
219
- startsAt: formatOLDate(seasonStart),
220
- endsAt: formatOLDate(seasonEnd),
221
- },
222
- rules: [
223
- {
224
- name: `Bonus for completing ${milestoneLabel}`,
225
- effects: [
226
- {
227
- effect: "give_points",
228
- pointsRule: { fixedValue: bonusCoins },
229
- },
230
- ],
231
- conditions: [
232
- {
233
- operator: "is_equal",
234
- attribute: "achievement.achievementId",
235
- data: { value: achievementId },
236
- },
237
- ],
238
- },
239
- ],
240
- active: true,
241
- });
242
- return { campaignId: response.campaignId };
243
- }
244
- catch (error) {
245
- return {
246
- error: `Failed to create bonus campaign for ${milestone}: ${error instanceof Error ? error.message : String(error)}`,
247
- };
248
- }
249
- }
250
- async function verifySetup(result) {
251
- const warnings = [];
252
- try {
253
- // Verify campaigns exist
254
- if (result.baseCampaignId) {
255
- const campaigns = await campaignList({ active: true });
256
- const found = campaigns.campaigns.some((c) => c.campaignId === result.baseCampaignId);
257
- if (!found) {
258
- warnings.push("Base campaign created but not found in active campaigns list");
259
- }
260
- }
261
- // Verify achievements exist
262
- if (result.achievements.length > 0) {
263
- const achievements = await achievementList({ active: true });
264
- for (const ach of result.achievements) {
265
- const found = achievements.achievements.some((a) => a.achievementId === ach.achievementId);
266
- if (!found) {
267
- warnings.push(`Achievement ${ach.milestone} created but not found in active achievements list`);
268
- }
269
- }
270
- }
271
- }
272
- catch (error) {
273
- warnings.push(`Verification error: ${error instanceof Error ? error.message : String(error)}`);
274
- }
275
- return { warnings };
276
- }
277
- function buildSummary(cfg, result) {
278
- const lines = [];
279
- if (result.baseCampaignId) {
280
- lines.push(`Fans will earn ${cfg.coinsPerMatch} coins per match attended`);
281
- }
282
- if (result.achievements.length > 0) {
283
- lines.push(`\nMilestone achievements created:`);
284
- for (const ach of result.achievements) {
285
- const bonusText = ach.bonusCampaignId
286
- ? ` (+ ${cfg.milestoneBonuses[result.achievements.indexOf(ach)] || 500} coin bonus)`
287
- : "";
288
- lines.push(`- ${ach.milestone} matches: ${ach.badgeName} badge${bonusText}`);
289
- }
290
- }
291
- lines.push(`\nSeason: ${cfg.seasonStart} to ${cfg.seasonEnd}`);
292
- lines.push(`Anti-fraud: Max ${cfg.limitPerDay} attendance${cfg.limitPerDay > 1 ? "s" : ""} per day`);
293
- if (result.errors.length > 0) {
294
- lines.push(`\nWarnings/Errors:`);
295
- for (const error of result.errors) {
296
- lines.push(`- ${error}`);
297
- }
298
- }
299
- return lines.join("\n");
300
- }
301
- // ============================================================================
302
- // Exports
303
- // ============================================================================
304
- export const matchAttendanceWorkflow = {
305
- id: "match-attendance",
306
- name: "Match Attendance Campaign",
307
- execute: executeMatchAttendanceWorkflow,
308
- };
@@ -1,41 +0,0 @@
1
- /**
2
- * Sports Bar Visit Workflow
3
- *
4
- * Creates a campaign to reward fans for visiting the sports bar,
5
- * with optional achievement for visiting multiple times.
6
- */
7
- export interface SportsbarVisitConfig {
8
- /** Coins awarded per visit */
9
- coinsPerVisit: number;
10
- /** Whether to create achievement for multiple visits */
11
- createAchievement: boolean;
12
- /** Number of visits for achievement milestone */
13
- visitMilestone: number;
14
- /** Bonus coins for completing the achievement */
15
- milestoneBonus: number;
16
- /** Maximum visits counted per day (anti-abuse) */
17
- limitPerDay: number;
18
- /** Badge name for achievement (optional) */
19
- badgeName?: string;
20
- /** Season start date (ISO format) */
21
- seasonStart: string;
22
- /** Season end date (ISO format) */
23
- seasonEnd: string;
24
- }
25
- export interface SportsbarVisitResult {
26
- success: boolean;
27
- visitCampaignId?: string;
28
- achievementId?: string;
29
- bonusCampaignId?: string;
30
- errors: string[];
31
- summary: string;
32
- }
33
- /**
34
- * Execute the sports bar visit workflow
35
- */
36
- export declare function executeSportsbarVisitWorkflow(config?: Partial<SportsbarVisitConfig>): Promise<SportsbarVisitResult>;
37
- export declare const sportsbarVisitWorkflow: {
38
- id: string;
39
- name: string;
40
- execute: typeof executeSportsbarVisitWorkflow;
41
- };
@@ -1,284 +0,0 @@
1
- /**
2
- * Sports Bar Visit Workflow
3
- *
4
- * Creates a campaign to reward fans for visiting the sports bar,
5
- * with optional achievement for visiting multiple times.
6
- */
7
- import { campaignCreate, campaignList } from "../tools/campaign/handlers.js";
8
- import { achievementCreate, achievementList } from "../tools/achievement.js";
9
- import { badgeList } from "../tools/badge.js";
10
- import { formatOLDate, DEFAULTS } from "../prompts/fan-engagement-setup.js";
11
- // ============================================================================
12
- // Workflow Implementation
13
- // ============================================================================
14
- /**
15
- * Execute the sports bar visit workflow
16
- */
17
- export async function executeSportsbarVisitWorkflow(config = {}) {
18
- const result = {
19
- success: false,
20
- errors: [],
21
- summary: "",
22
- };
23
- // Merge with defaults
24
- const cfg = {
25
- coinsPerVisit: config.coinsPerVisit ?? DEFAULTS.sportsbarVisit.coinsPerVisit,
26
- createAchievement: config.createAchievement ?? true,
27
- visitMilestone: config.visitMilestone ?? DEFAULTS.sportsbarVisit.visitMilestone,
28
- milestoneBonus: config.milestoneBonus ?? DEFAULTS.sportsbarVisit.milestoneBonus,
29
- limitPerDay: config.limitPerDay ?? DEFAULTS.sportsbarVisit.limitPerDay,
30
- badgeName: config.badgeName ?? "Sports Bar Regular",
31
- seasonStart: config.seasonStart ?? DEFAULTS.seasonDates.start,
32
- seasonEnd: config.seasonEnd ?? DEFAULTS.seasonDates.end,
33
- };
34
- try {
35
- // Step 1: Create base visit campaign
36
- const visitCampaignResult = await createVisitCampaign(cfg);
37
- if (visitCampaignResult.error) {
38
- result.errors.push(visitCampaignResult.error);
39
- }
40
- else {
41
- result.visitCampaignId = visitCampaignResult.campaignId;
42
- }
43
- // Step 2: Create achievement and bonus campaign if enabled
44
- if (cfg.createAchievement) {
45
- // Get available badges
46
- const badges = await getAvailableBadges();
47
- const achievementResult = await createVisitAchievement(cfg, badges);
48
- if (achievementResult.error) {
49
- result.errors.push(achievementResult.error);
50
- }
51
- else {
52
- result.achievementId = achievementResult.achievementId;
53
- // Create bonus campaign for achievement
54
- if (achievementResult.achievementId) {
55
- const bonusCampaignResult = await createAchievementBonusCampaign(achievementResult.achievementId, cfg);
56
- if (bonusCampaignResult.error) {
57
- result.errors.push(bonusCampaignResult.error);
58
- }
59
- else {
60
- result.bonusCampaignId = bonusCampaignResult.campaignId;
61
- }
62
- }
63
- }
64
- }
65
- // Step 3: Verify setup
66
- const verification = await verifySetup(result);
67
- if (verification.warnings.length > 0) {
68
- result.errors.push(...verification.warnings);
69
- }
70
- // Determine success
71
- result.success = result.visitCampaignId !== undefined && result.errors.length === 0;
72
- // Build summary
73
- result.summary = buildSummary(cfg, result);
74
- }
75
- catch (error) {
76
- result.errors.push(`Workflow error: ${error instanceof Error ? error.message : String(error)}`);
77
- }
78
- return result;
79
- }
80
- // ============================================================================
81
- // Helper Functions
82
- // ============================================================================
83
- async function createVisitCampaign(cfg) {
84
- try {
85
- const response = await campaignCreate({
86
- type: "direct",
87
- trigger: "custom_event",
88
- event: "sportsbar_visit",
89
- translations: {
90
- en: {
91
- name: "Sports Bar Visit Reward",
92
- description: `Earn ${cfg.coinsPerVisit} coins for each visit to the sports bar`,
93
- },
94
- },
95
- activity: {
96
- startsAt: formatOLDate(cfg.seasonStart),
97
- endsAt: formatOLDate(cfg.seasonEnd),
98
- },
99
- rules: [
100
- {
101
- name: "Award coins for sports bar visit",
102
- effects: [
103
- {
104
- effect: "give_points",
105
- pointsRule: { fixedValue: cfg.coinsPerVisit },
106
- },
107
- ],
108
- },
109
- ],
110
- limits: {
111
- executionsPerMember: {
112
- value: cfg.limitPerDay,
113
- interval: { type: "days", value: 1 },
114
- },
115
- },
116
- active: true,
117
- });
118
- return { campaignId: response.campaignId };
119
- }
120
- catch (error) {
121
- return {
122
- error: `Failed to create visit campaign: ${error instanceof Error ? error.message : String(error)}`,
123
- };
124
- }
125
- }
126
- async function getAvailableBadges() {
127
- try {
128
- const response = await badgeList({});
129
- const badgeMap = new Map();
130
- for (const badge of response.badges) {
131
- if (badge.name && badge.badgeTypeId) {
132
- badgeMap.set(badge.name.toLowerCase(), badge.badgeTypeId);
133
- }
134
- }
135
- return badgeMap;
136
- }
137
- catch {
138
- return new Map();
139
- }
140
- }
141
- async function createVisitAchievement(cfg, badges) {
142
- try {
143
- const badgeTypeId = cfg.badgeName
144
- ? badges.get(cfg.badgeName.toLowerCase())
145
- : undefined;
146
- const achievementPayload = {
147
- translations: {
148
- en: {
149
- name: `${cfg.visitMilestone} Sports Bar Visits`,
150
- description: `Visit the sports bar ${cfg.visitMilestone} times this season`,
151
- },
152
- },
153
- active: true,
154
- activity: {
155
- startsAt: formatOLDate(cfg.seasonStart),
156
- endsAt: formatOLDate(cfg.seasonEnd),
157
- },
158
- rules: [
159
- {
160
- trigger: "custom_event",
161
- event: "sportsbar_visit",
162
- completeRule: {
163
- periodGoal: cfg.visitMilestone,
164
- },
165
- },
166
- ],
167
- };
168
- if (badgeTypeId) {
169
- achievementPayload.badgeTypeId = badgeTypeId;
170
- }
171
- const response = await achievementCreate(achievementPayload);
172
- return { achievementId: response.achievementId };
173
- }
174
- catch (error) {
175
- return {
176
- error: `Failed to create visit achievement: ${error instanceof Error ? error.message : String(error)}`,
177
- };
178
- }
179
- }
180
- async function createAchievementBonusCampaign(achievementId, cfg) {
181
- try {
182
- const response = await campaignCreate({
183
- type: "direct",
184
- trigger: "achievement",
185
- translations: {
186
- en: {
187
- name: `Sports Bar ${cfg.visitMilestone} Visits Bonus`,
188
- description: `Bonus ${cfg.milestoneBonus} coins for visiting the sports bar ${cfg.visitMilestone} times`,
189
- },
190
- },
191
- activity: {
192
- startsAt: formatOLDate(cfg.seasonStart),
193
- endsAt: formatOLDate(cfg.seasonEnd),
194
- },
195
- rules: [
196
- {
197
- name: `Bonus for ${cfg.visitMilestone} visits`,
198
- effects: [
199
- {
200
- effect: "give_points",
201
- pointsRule: { fixedValue: cfg.milestoneBonus },
202
- },
203
- ],
204
- conditions: [
205
- {
206
- operator: "is_equal",
207
- attribute: "achievement.achievementId",
208
- data: { value: achievementId },
209
- },
210
- ],
211
- },
212
- ],
213
- active: true,
214
- });
215
- return { campaignId: response.campaignId };
216
- }
217
- catch (error) {
218
- return {
219
- error: `Failed to create bonus campaign: ${error instanceof Error ? error.message : String(error)}`,
220
- };
221
- }
222
- }
223
- async function verifySetup(result) {
224
- const warnings = [];
225
- try {
226
- if (result.visitCampaignId) {
227
- const campaigns = await campaignList({ active: true });
228
- const found = campaigns.campaigns.some((c) => c.campaignId === result.visitCampaignId);
229
- if (!found) {
230
- warnings.push("Visit campaign created but not found in active campaigns list");
231
- }
232
- }
233
- if (result.achievementId) {
234
- const achievements = await achievementList({ active: true });
235
- const found = achievements.achievements.some((a) => a.achievementId === result.achievementId);
236
- if (!found) {
237
- warnings.push("Achievement created but not found in active achievements list");
238
- }
239
- }
240
- }
241
- catch (error) {
242
- warnings.push(`Verification error: ${error instanceof Error ? error.message : String(error)}`);
243
- }
244
- return { warnings };
245
- }
246
- function buildSummary(cfg, result) {
247
- const lines = [];
248
- if (result.visitCampaignId) {
249
- lines.push(`Sports bar visit campaign created!`);
250
- lines.push(`\nPer-visit reward: ${cfg.coinsPerVisit} coins`);
251
- lines.push(`Daily limit: ${cfg.limitPerDay} visit${cfg.limitPerDay > 1 ? "s" : ""}`);
252
- }
253
- if (result.achievementId) {
254
- lines.push(`\nAchievement: Visit ${cfg.visitMilestone} times`);
255
- if (cfg.badgeName) {
256
- lines.push(`Badge: ${cfg.badgeName}`);
257
- }
258
- if (result.bonusCampaignId) {
259
- lines.push(`Completion bonus: ${cfg.milestoneBonus} coins`);
260
- }
261
- }
262
- lines.push(`\nSeason: ${cfg.seasonStart} to ${cfg.seasonEnd}`);
263
- lines.push(`\nCustom event to trigger reward:`);
264
- lines.push(` Event: sportsbar_visit`);
265
- lines.push(`\nExample event payload:`);
266
- lines.push(`{`);
267
- lines.push(` "event": "sportsbar_visit"`);
268
- lines.push(`}`);
269
- if (result.errors.length > 0) {
270
- lines.push(`\nWarnings/Errors:`);
271
- for (const error of result.errors) {
272
- lines.push(`- ${error}`);
273
- }
274
- }
275
- return lines.join("\n");
276
- }
277
- // ============================================================================
278
- // Exports
279
- // ============================================================================
280
- export const sportsbarVisitWorkflow = {
281
- id: "sportsbar-visit",
282
- name: "Sports Bar Visit Campaign",
283
- execute: executeSportsbarVisitWorkflow,
284
- };
@@ -1,43 +0,0 @@
1
- /**
2
- * VOD Watching Workflow
3
- *
4
- * Creates a campaign to reward fans for watching video content,
5
- * with achievements for total watch time using attribute aggregation.
6
- */
7
- export interface VodWatchingConfig {
8
- /** Track by "views" or "minutes" */
9
- trackBy: "views" | "minutes";
10
- /** Coins awarded per unit (view or unitSize minutes) */
11
- coinsPerUnit: number;
12
- /** For minutes tracking: how many minutes per reward unit */
13
- unitSize: number;
14
- /** Whether to create achievement for total watching */
15
- createAchievement: boolean;
16
- /** Target for achievement (minutes or views) */
17
- achievementTarget: number;
18
- /** Bonus coins for completing the achievement */
19
- achievementBonus: number;
20
- /** Badge name for achievement (optional) */
21
- badgeName?: string;
22
- /** Season start date (ISO format) */
23
- seasonStart: string;
24
- /** Season end date (ISO format) */
25
- seasonEnd: string;
26
- }
27
- export interface VodWatchingResult {
28
- success: boolean;
29
- watchCampaignId?: string;
30
- achievementId?: string;
31
- bonusCampaignId?: string;
32
- errors: string[];
33
- summary: string;
34
- }
35
- /**
36
- * Execute the VOD watching workflow
37
- */
38
- export declare function executeVodWatchingWorkflow(config?: Partial<VodWatchingConfig>): Promise<VodWatchingResult>;
39
- export declare const vodWatchingWorkflow: {
40
- id: string;
41
- name: string;
42
- execute: typeof executeVodWatchingWorkflow;
43
- };