@burgan-tech/morph-touch-runtime 0.0.7 → 0.0.9

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 (68) hide show
  1. package/burgan-tech-morph-touch-runtime-0.0.9.tgz +0 -0
  2. package/morph-touch/Functions/get-absence-entry.1.0.0.json +1 -1
  3. package/morph-touch/Functions/get-advisor-stats.1.0.0.json +1 -1
  4. package/morph-touch/Functions/get-available-slots.1.0.0.json +1 -1
  5. package/morph-touch/Functions/get-chat-rooms.http +4 -4
  6. package/morph-touch/Functions/get-rezervations.1.0.0.json +1 -1
  7. package/morph-touch/Functions/src/GetAbsenceEntryMapping.csx +18 -4
  8. package/morph-touch/Functions/src/GetAdvisorStatsMapping.csx +22 -8
  9. package/morph-touch/Functions/src/GetAvailableSlotsMapping.csx +22 -14
  10. package/morph-touch/Functions/src/GetRezervationsMapping.csx +19 -2
  11. package/morph-touch/Functions/src/SendCancelNotificationMapping.csx +27 -2
  12. package/morph-touch/Tasks/check-existing-permanent-chat-room.1.0.0.json +1 -1
  13. package/morph-touch/Tasks/login-for-chat.1.0.0.json +27 -0
  14. package/morph-touch/Tasks/register-for-chat.1.0.0.json +27 -0
  15. package/morph-touch/Tasks/start-register-matrix-user.1.0.0.json +22 -0
  16. package/morph-touch/Workflows/chat-room.json +196 -14
  17. package/morph-touch/Workflows/notification-sender.json +2 -2
  18. package/morph-touch/Workflows/register-matrix-user.json +128 -0
  19. package/morph-touch/Workflows/rezervation-start.json +28 -2
  20. package/morph-touch/Workflows/rezervation-transfer.json +34 -8
  21. package/morph-touch/Workflows/rezervation-update.json +5 -5
  22. package/morph-touch/Workflows/rezervation.json +135 -45
  23. package/morph-touch/Workflows/src/AlwaysTrueRule.csx +0 -3
  24. package/morph-touch/Workflows/src/CanStartRezervationTimerMapping.csx +18 -3
  25. package/morph-touch/Workflows/src/ChatRoomRemoveMapping.csx +10 -1
  26. package/morph-touch/Workflows/src/ChatRoomTransferInviteMapping.csx +10 -1
  27. package/morph-touch/Workflows/src/ChatRoomTransferRemoveMapping.csx +9 -1
  28. package/morph-touch/Workflows/src/ChatRoomUpdateMapping.csx +10 -1
  29. package/morph-touch/Workflows/src/CheckDuplicateRezervationMapping.csx +17 -3
  30. package/morph-touch/Workflows/src/CheckExistingPermanentChatRoomMapping.csx +4 -7
  31. package/morph-touch/Workflows/src/CheckRandevuTimeMapping.csx +16 -2
  32. package/morph-touch/Workflows/src/CreateChatRoomForRezervationMapping.csx +12 -2
  33. package/morph-touch/Workflows/src/CreatePermanentChatRoomMapping.csx +11 -1
  34. package/morph-touch/Workflows/src/EnrichRezervationsForTransferMapping.csx +18 -4
  35. package/morph-touch/Workflows/src/FetchRoomMessagesForSummaryMapping.csx +10 -2
  36. package/morph-touch/Workflows/src/InviteAdvisorForRandevuUpdateMapping.csx +10 -1
  37. package/morph-touch/Workflows/src/InviteNewAdvisorToRezervationRoomMapping.csx +11 -2
  38. package/morph-touch/Workflows/src/InviteNewParticipantToRandevuRoomMapping.csx +10 -1
  39. package/morph-touch/Workflows/src/JoinChatRoomForAddParticipantMapping.csx +5 -1
  40. package/morph-touch/Workflows/src/JoinChatRoomForRandevuStartMapping.csx +5 -1
  41. package/morph-touch/Workflows/src/JoinChatRoomForRezervationMapping.csx +4 -0
  42. package/morph-touch/Workflows/src/JoinMatrixRoomMapping.csx +11 -1
  43. package/morph-touch/Workflows/src/JoinUserToRoomMapping.csx +6 -0
  44. package/morph-touch/Workflows/src/LoginForAddParticipantChatMapping.csx +35 -6
  45. package/morph-touch/Workflows/src/LoginForChatRoomMapping.csx +121 -0
  46. package/morph-touch/Workflows/src/LoginForJoinUserToRoomMapping.csx +142 -0
  47. package/morph-touch/Workflows/src/LoginForRandevuStartChatMapping.csx +35 -10
  48. package/morph-touch/Workflows/src/LoginForTransferChatMapping.csx +153 -0
  49. package/morph-touch/Workflows/src/RegisterForAddParticipantChatMapping.csx +74 -0
  50. package/morph-touch/Workflows/src/RegisterForChatRoomMapping.csx +52 -0
  51. package/morph-touch/Workflows/src/RegisterForJoinUserToRoomMapping.csx +63 -0
  52. package/morph-touch/Workflows/src/RegisterForRandevuStartChatMapping.csx +56 -0
  53. package/morph-touch/Workflows/src/RegisterForTransferChatMapping.csx +90 -0
  54. package/morph-touch/Workflows/src/RegisterMatrixUserMapping.csx +73 -0
  55. package/morph-touch/Workflows/src/SendPushNotificationMapping.csx +25 -4
  56. package/morph-touch/Workflows/src/SendSmsNotificationMapping.csx +25 -4
  57. package/morph-touch/Workflows/src/SendSummaryToNewRoomMapping.csx +10 -2
  58. package/morph-touch/Workflows/src/SetRoomHistoryVisibilityMapping.csx +12 -4
  59. package/morph-touch/Workflows/src/ValidateDateForRezervationMapping.csx +16 -2
  60. package/morph-touch/Workflows/src/ValidateSlotForRandevuUpdateMapping.csx +22 -15
  61. package/morph-touch/Workflows/src/ValidateSlotForRezervationMapping.csx +23 -16
  62. package/morph-touch/Workflows/src/ValidateTransferMapping.csx +16 -2
  63. package/morph-touch/Workflows/start-chat.json +1 -1
  64. package/morph-touch/doc/morph-touch-domain.en.md +1 -1
  65. package/morph-touch/doc/morph-touch-domain.md +1 -1
  66. package/package.json +1 -1
  67. package/vnext.config.json +1 -1
  68. package/burgan-tech-morph-touch-runtime-0.0.7.tgz +0 -0
@@ -0,0 +1,121 @@
1
+ using System;
2
+ using System.Collections.Generic;
3
+ using System.Threading.Tasks;
4
+ using BBT.Workflow.Scripting;
5
+ using BBT.Workflow.Definitions;
6
+
7
+ /// <summary>
8
+ /// Mapping for login-for-chat when used in chat-room workflow.
9
+ /// Calls POST /_matrix/client/v3/login on Synapse.
10
+ /// Logs in as data.user (the customer/room owner).
11
+ /// Stores access_token as sessionId in chatIntegration for subsequent Matrix API calls.
12
+ /// </summary>
13
+ public class LoginForChatRoomMapping : ScriptBase, IMapping
14
+ {
15
+ public async Task<ScriptResponse> InputHandler(WorkflowTask task, ScriptContext context)
16
+ {
17
+ var httpTask = task as HttpTask;
18
+ if (httpTask == null)
19
+ throw new InvalidOperationException("Task must be an HttpTask");
20
+
21
+ var secretName = GetConfigValue("DAPR_SECRET_STORE_NAME");
22
+ if (string.IsNullOrWhiteSpace(secretName))
23
+ throw new InvalidOperationException("DAPR_SECRET_STORE_NAME configuration is required");
24
+
25
+ var matrixBaseUrl = await GetSecretAsync(secretName, "workflow-secret", "MatrixBaseUrl");
26
+ if (string.IsNullOrWhiteSpace(matrixBaseUrl))
27
+ throw new InvalidOperationException("MatrixBaseUrl secret is required");
28
+
29
+ var synapsePassword = await GetSecretAsync(secretName, "workflow-secret", "SynapsePassword");
30
+ if (string.IsNullOrWhiteSpace(synapsePassword))
31
+ throw new InvalidOperationException("SynapsePassword secret is required");
32
+
33
+ var data = context.Instance?.Data;
34
+ var loginUsername = GetString(data, "user");
35
+ if (string.IsNullOrWhiteSpace(loginUsername))
36
+ throw new InvalidOperationException("Cannot determine login user: data.user is missing");
37
+
38
+ var fullUrl = matrixBaseUrl.TrimEnd('/') + "/_matrix/client/v3/login";
39
+ httpTask.SetUrl(fullUrl);
40
+
41
+ httpTask.SetHeaders(new Dictionary<string, string>
42
+ {
43
+ ["Content-Type"] = "application/json",
44
+ ["Accept"] = "application/json"
45
+ });
46
+
47
+ httpTask.SetBody(new
48
+ {
49
+ type = "m.login.password",
50
+ identifier = new { type = "m.id.user", user = "u" + loginUsername },
51
+ password = synapsePassword
52
+ });
53
+ return new ScriptResponse();
54
+ }
55
+
56
+ public Task<ScriptResponse> OutputHandler(ScriptContext context)
57
+ {
58
+ var result = new ScriptResponse();
59
+ var response = context.Body;
60
+ var instanceData = context.Instance?.Data;
61
+
62
+ string existingRoomId = null;
63
+ if (instanceData != null && HasProperty(instanceData, "chatIntegration") && instanceData.chatIntegration != null)
64
+ existingRoomId = GetString(instanceData.chatIntegration, "roomId");
65
+
66
+ if (response?.isSuccess == true)
67
+ {
68
+ dynamic data = response.data;
69
+ string sessionId = GetString(data, "access_token");
70
+ string userId = GetString(data, "user_id");
71
+ string username = GetString(data, "username");
72
+
73
+ result.Data = new
74
+ {
75
+ chatIntegration = new
76
+ {
77
+ sessionId,
78
+ userId,
79
+ username,
80
+ roomId = existingRoomId,
81
+ error = (string)null,
82
+ errorCode = (string)null
83
+ }
84
+ };
85
+ }
86
+ else
87
+ {
88
+ string errorMessage = response?.errorMessage?.ToString() ?? "Chat login failed";
89
+ string statusCode = response?.statusCode != null ? response.statusCode.ToString() : null;
90
+ result.Data = new
91
+ {
92
+ chatIntegration = new
93
+ {
94
+ sessionId = (string)null,
95
+ userId = (string)null,
96
+ username = (string)null,
97
+ roomId = existingRoomId,
98
+ error = errorMessage,
99
+ errorCode = statusCode
100
+ }
101
+ };
102
+ }
103
+
104
+ return Task.FromResult(result);
105
+ }
106
+
107
+ private string GetString(dynamic obj, string name)
108
+ {
109
+ if (obj == null) return null;
110
+ try
111
+ {
112
+ if (HasProperty(obj, name))
113
+ {
114
+ var v = GetPropertyValue(obj, name);
115
+ return v?.ToString();
116
+ }
117
+ }
118
+ catch { }
119
+ return null;
120
+ }
121
+ }
@@ -0,0 +1,142 @@
1
+ using System;
2
+ using System.Collections.Generic;
3
+ using System.Threading.Tasks;
4
+ using BBT.Workflow.Scripting;
5
+ using BBT.Workflow.Definitions;
6
+
7
+ /// <summary>
8
+ /// Mapping for login-for-chat when the next step is join-user-to-room.
9
+ /// Logs in as the user who will join the room (pendingJoinUserId / newAdvisorId / advisorId).
10
+ /// Stores access_token in chatIntegration.joinSessionId so JoinUserToRoomMapping
11
+ /// uses the correct token without overwriting the room-owner's sessionId.
12
+ /// </summary>
13
+ public class LoginForJoinUserToRoomMapping : ScriptBase, IMapping
14
+ {
15
+ public async Task<ScriptResponse> InputHandler(WorkflowTask task, ScriptContext context)
16
+ {
17
+ var httpTask = task as HttpTask;
18
+ if (httpTask == null)
19
+ throw new InvalidOperationException("Task must be an HttpTask");
20
+
21
+ var data = context.Instance?.Data;
22
+
23
+ var joinUser = GetString(data, "pendingJoinUserId");
24
+ if (string.IsNullOrWhiteSpace(joinUser))
25
+ joinUser = GetString(data, "newAdvisorId");
26
+ if (string.IsNullOrWhiteSpace(joinUser))
27
+ joinUser = GetString(data, "advisorId");
28
+
29
+ if (string.IsNullOrWhiteSpace(joinUser))
30
+ return new ScriptResponse();
31
+
32
+ var loginUsername = joinUser.Trim();
33
+ if (loginUsername.StartsWith("@"))
34
+ {
35
+ var colonIdx = loginUsername.IndexOf(':');
36
+ loginUsername = colonIdx > 0 ? loginUsername.Substring(1, colonIdx - 1) : loginUsername.Substring(1);
37
+ }
38
+
39
+ var secretName = GetConfigValue("DAPR_SECRET_STORE_NAME");
40
+ if (string.IsNullOrWhiteSpace(secretName))
41
+ throw new InvalidOperationException("DAPR_SECRET_STORE_NAME configuration is required");
42
+
43
+ var matrixBaseUrl = await GetSecretAsync(secretName, "workflow-secret", "MatrixBaseUrl");
44
+ if (string.IsNullOrWhiteSpace(matrixBaseUrl))
45
+ throw new InvalidOperationException("MatrixBaseUrl secret is required");
46
+
47
+ var synapsePassword = await GetSecretAsync(secretName, "workflow-secret", "SynapsePassword");
48
+ if (string.IsNullOrWhiteSpace(synapsePassword))
49
+ throw new InvalidOperationException("SynapsePassword secret is required");
50
+
51
+ var fullUrl = matrixBaseUrl.TrimEnd('/') + "/_matrix/client/v3/login";
52
+ httpTask.SetUrl(fullUrl);
53
+
54
+ httpTask.SetHeaders(new Dictionary<string, string>
55
+ {
56
+ ["Content-Type"] = "application/json",
57
+ ["Accept"] = "application/json"
58
+ });
59
+
60
+ httpTask.SetBody(new
61
+ {
62
+ type = "m.login.password",
63
+ identifier = new { type = "m.id.user", user = loginUsername },
64
+ password = synapsePassword
65
+ });
66
+ return new ScriptResponse();
67
+ }
68
+
69
+ public Task<ScriptResponse> OutputHandler(ScriptContext context)
70
+ {
71
+ var result = new ScriptResponse();
72
+ var response = context.Body;
73
+ var instanceData = context.Instance?.Data;
74
+
75
+ string existingSessionId = null;
76
+ string existingUserId = null;
77
+ string existingUsername = null;
78
+ string existingRoomId = null;
79
+ if (instanceData != null && HasProperty(instanceData, "chatIntegration") && instanceData.chatIntegration != null)
80
+ {
81
+ existingSessionId = GetString(instanceData.chatIntegration, "sessionId");
82
+ existingUserId = GetString(instanceData.chatIntegration, "userId");
83
+ existingUsername = GetString(instanceData.chatIntegration, "username");
84
+ existingRoomId = GetString(instanceData.chatIntegration, "roomId");
85
+ }
86
+
87
+ if (response?.isSuccess == true)
88
+ {
89
+ dynamic data = response.data;
90
+ string joinSessionId = GetString(data, "access_token");
91
+
92
+ result.Data = new
93
+ {
94
+ chatIntegration = new
95
+ {
96
+ sessionId = existingSessionId,
97
+ userId = existingUserId,
98
+ username = existingUsername,
99
+ roomId = existingRoomId,
100
+ joinSessionId,
101
+ error = (string)null,
102
+ errorCode = (string)null
103
+ }
104
+ };
105
+ }
106
+ else
107
+ {
108
+ string errorMessage = response?.errorMessage?.ToString() ?? "Join user login failed";
109
+ string statusCode = response?.statusCode != null ? response.statusCode.ToString() : null;
110
+ result.Data = new
111
+ {
112
+ chatIntegration = new
113
+ {
114
+ sessionId = existingSessionId,
115
+ userId = existingUserId,
116
+ username = existingUsername,
117
+ roomId = existingRoomId,
118
+ joinSessionId = (string)null,
119
+ error = errorMessage,
120
+ errorCode = statusCode
121
+ }
122
+ };
123
+ }
124
+
125
+ return Task.FromResult(result);
126
+ }
127
+
128
+ private string GetString(dynamic obj, string name)
129
+ {
130
+ if (obj == null) return null;
131
+ try
132
+ {
133
+ if (HasProperty(obj, name))
134
+ {
135
+ var v = GetPropertyValue(obj, name);
136
+ return v?.ToString();
137
+ }
138
+ }
139
+ catch { }
140
+ return null;
141
+ }
142
+ }
@@ -1,20 +1,35 @@
1
1
  using System;
2
+ using System.Collections.Generic;
2
3
  using System.Threading.Tasks;
3
4
  using BBT.Workflow.Scripting;
4
5
  using BBT.Workflow.Definitions;
5
6
 
6
7
  /// <summary>
7
8
  /// Mapping for login-for-rezervation-chat when used in rezervation-start flow.
9
+ /// Calls POST /_matrix/client/v3/login on Synapse.
8
10
  /// Uses participantType to determine login user: advisor, customer (user), or invited (invitedUserId).
11
+ /// Stores access_token as sessionId in chatIntegration for subsequent Matrix API calls.
9
12
  /// </summary>
10
13
  public class LoginForRandevuStartChatMapping : ScriptBase, IMapping
11
14
  {
12
- public Task<ScriptResponse> InputHandler(WorkflowTask task, ScriptContext context)
15
+ public async Task<ScriptResponse> InputHandler(WorkflowTask task, ScriptContext context)
13
16
  {
14
17
  var httpTask = task as HttpTask;
15
18
  if (httpTask == null)
16
19
  throw new InvalidOperationException("Task must be an HttpTask");
17
20
 
21
+ var secretName = GetConfigValue("DAPR_SECRET_STORE_NAME");
22
+ if (string.IsNullOrWhiteSpace(secretName))
23
+ throw new InvalidOperationException("DAPR_SECRET_STORE_NAME configuration is required");
24
+
25
+ var matrixBaseUrl = await GetSecretAsync(secretName, "workflow-secret", "MatrixBaseUrl");
26
+ if (string.IsNullOrWhiteSpace(matrixBaseUrl))
27
+ throw new InvalidOperationException("MatrixBaseUrl secret is required");
28
+
29
+ var synapsePassword = await GetSecretAsync(secretName, "workflow-secret", "SynapsePassword");
30
+ if (string.IsNullOrWhiteSpace(synapsePassword))
31
+ throw new InvalidOperationException("SynapsePassword secret is required");
32
+
18
33
  var data = context.Instance?.Data;
19
34
  var participantType = GetString(data, "participantType");
20
35
  var user = GetString(data, "user");
@@ -22,12 +37,26 @@ public class LoginForRandevuStartChatMapping : ScriptBase, IMapping
22
37
 
23
38
  var loginUsername = participantType == "advisor" ? advisor
24
39
  : participantType == "invited" ? GetString(data, "invitedUserId")
25
- : user;
40
+ : "u"+user;
26
41
  if (string.IsNullOrWhiteSpace(loginUsername))
27
42
  throw new InvalidOperationException("Cannot determine login user: participantType, user, advisor, or invitedUserId missing");
28
43
 
29
- httpTask.SetBody(new { Username = loginUsername });
30
- return Task.FromResult(new ScriptResponse());
44
+ var fullUrl = matrixBaseUrl.TrimEnd('/') + "/_matrix/client/v3/login";
45
+ httpTask.SetUrl(fullUrl);
46
+
47
+ httpTask.SetHeaders(new Dictionary<string, string>
48
+ {
49
+ ["Content-Type"] = "application/json",
50
+ ["Accept"] = "application/json"
51
+ });
52
+
53
+ httpTask.SetBody(new
54
+ {
55
+ type = "m.login.password",
56
+ identifier = new { type = "m.id.user", user = loginUsername },
57
+ password = synapsePassword
58
+ });
59
+ return new ScriptResponse();
31
60
  }
32
61
 
33
62
  public Task<ScriptResponse> OutputHandler(ScriptContext context)
@@ -38,14 +67,10 @@ public class LoginForRandevuStartChatMapping : ScriptBase, IMapping
38
67
  if (response?.isSuccess == true)
39
68
  {
40
69
  dynamic data = response.data;
41
- string sessionId = GetString(data, "sessionId");
42
- string userId = GetString(data, "userId");
70
+ string sessionId = GetString(data, "access_token");
71
+ string userId = GetString(data, "user_id");
43
72
  string username = GetString(data, "username");
44
73
 
45
- var instanceData = context.Instance?.Data;
46
- // var existingChat = instanceData?.chatIntegration;
47
- // string roomId = GetString(existingChat, "roomId");
48
-
49
74
  result.Data = new
50
75
  {
51
76
  chatIntegration = new
@@ -0,0 +1,153 @@
1
+ using System;
2
+ using System.Collections.Generic;
3
+ using System.Linq;
4
+ using System.Threading.Tasks;
5
+ using BBT.Workflow.Scripting;
6
+ using BBT.Workflow.Definitions;
7
+
8
+ /// <summary>
9
+ /// Mapping for login-for-chat when used in rezervation-transfer flow.
10
+ /// Calls POST /_matrix/client/v3/login on Synapse.
11
+ /// Looks up user from permanentChatRooms by chatRoomKey (same logic as FetchRoomMessagesForSummaryMapping).
12
+ /// Stores access_token as sessionId in chatIntegration for subsequent Matrix API calls.
13
+ /// </summary>
14
+ public class LoginForTransferChatMapping : ScriptBase, IMapping
15
+ {
16
+ public async Task<ScriptResponse> InputHandler(WorkflowTask task, ScriptContext context)
17
+ {
18
+ var httpTask = task as HttpTask;
19
+ if (httpTask == null)
20
+ throw new InvalidOperationException("Task must be an HttpTask");
21
+
22
+ var data = context.Instance?.Data;
23
+ if (data == null)
24
+ return new ScriptResponse();
25
+
26
+ string user = null;
27
+ var permanentRoomPlan = data.permanentRoomPlan;
28
+ if (permanentRoomPlan != null)
29
+ {
30
+ int processedIndex = 0;
31
+ if (HasProperty(data, "permanentProcessedIndex"))
32
+ int.TryParse(data.permanentProcessedIndex?.ToString() ?? "0", out processedIndex);
33
+
34
+ var items = permanentRoomPlan as IEnumerable<object>;
35
+ if (items != null)
36
+ {
37
+ var itemsList = items.ToList();
38
+ if (processedIndex < itemsList.Count)
39
+ {
40
+ dynamic currentItem = itemsList[processedIndex];
41
+ var chatRoomKey = currentItem?.chatRoomKey?.ToString();
42
+ if (!string.IsNullOrEmpty(chatRoomKey))
43
+ user = LookupUser(data, chatRoomKey);
44
+ }
45
+ }
46
+ }
47
+
48
+ if (string.IsNullOrWhiteSpace(user))
49
+ return new ScriptResponse();
50
+
51
+ var secretName = GetConfigValue("DAPR_SECRET_STORE_NAME");
52
+ if (string.IsNullOrWhiteSpace(secretName))
53
+ throw new InvalidOperationException("DAPR_SECRET_STORE_NAME configuration is required");
54
+
55
+ var matrixBaseUrl = await GetSecretAsync(secretName, "workflow-secret", "MatrixBaseUrl");
56
+ if (string.IsNullOrWhiteSpace(matrixBaseUrl))
57
+ throw new InvalidOperationException("MatrixBaseUrl secret is required");
58
+
59
+ var synapsePassword = await GetSecretAsync(secretName, "workflow-secret", "SynapsePassword");
60
+ if (string.IsNullOrWhiteSpace(synapsePassword))
61
+ throw new InvalidOperationException("SynapsePassword secret is required");
62
+
63
+ var fullUrl = matrixBaseUrl.TrimEnd('/') + "/_matrix/client/v3/login";
64
+ httpTask.SetUrl(fullUrl);
65
+
66
+ httpTask.SetHeaders(new Dictionary<string, string>
67
+ {
68
+ ["Content-Type"] = "application/json",
69
+ ["Accept"] = "application/json"
70
+ });
71
+
72
+ httpTask.SetBody(new
73
+ {
74
+ type = "m.login.password",
75
+ identifier = new { type = "m.id.user", user = user },
76
+ password = synapsePassword
77
+ });
78
+ return new ScriptResponse();
79
+ }
80
+
81
+ public Task<ScriptResponse> OutputHandler(ScriptContext context)
82
+ {
83
+ var result = new ScriptResponse();
84
+ var response = context.Body;
85
+
86
+ if (response?.isSuccess == true)
87
+ {
88
+ dynamic data = response.data;
89
+ string sessionId = GetString(data, "access_token");
90
+ string userId = GetString(data, "user_id");
91
+ string username = GetString(data, "username");
92
+
93
+ result.Data = new
94
+ {
95
+ chatIntegration = new
96
+ {
97
+ sessionId,
98
+ userId,
99
+ username,
100
+ error = (string)null,
101
+ errorCode = (string)null
102
+ }
103
+ };
104
+ }
105
+ else
106
+ {
107
+ string errorMessage = response?.errorMessage?.ToString() ?? "Chat login failed";
108
+ string statusCode = response?.statusCode != null ? response.statusCode.ToString() : null;
109
+ result.Data = new
110
+ {
111
+ chatIntegration = new
112
+ {
113
+ sessionId = (string)null,
114
+ userId = (string)null,
115
+ username = (string)null,
116
+ error = errorMessage,
117
+ errorCode = statusCode
118
+ }
119
+ };
120
+ }
121
+
122
+ return Task.FromResult(result);
123
+ }
124
+
125
+ private string LookupUser(dynamic data, string chatRoomKey)
126
+ {
127
+ if (!HasProperty(data, "permanentChatRooms") || data.permanentChatRooms == null)
128
+ return null;
129
+
130
+ foreach (var room in data.permanentChatRooms)
131
+ {
132
+ var key = GetString(room, "chatRoomKey");
133
+ if (string.Equals(key, chatRoomKey, StringComparison.OrdinalIgnoreCase))
134
+ return GetString(room, "user");
135
+ }
136
+ return null;
137
+ }
138
+
139
+ private string GetString(dynamic obj, string name)
140
+ {
141
+ if (obj == null) return null;
142
+ try
143
+ {
144
+ if (HasProperty(obj, name))
145
+ {
146
+ var v = GetPropertyValue(obj, name);
147
+ return v?.ToString()?.Trim();
148
+ }
149
+ }
150
+ catch { }
151
+ return null;
152
+ }
153
+ }
@@ -0,0 +1,74 @@
1
+ using System;
2
+ using System.Collections.Generic;
3
+ using System.Threading.Tasks;
4
+ using BBT.Workflow.Scripting;
5
+ using BBT.Workflow.Definitions;
6
+
7
+ /// <summary>
8
+ /// Mapping for register-for-chat in add-participant flow.
9
+ /// Registers newUserId on Synapse via POST /_matrix/client/v3/register.
10
+ /// ErrorBoundary on the task ignores M_USER_IN_USE and other errors so login proceeds.
11
+ /// </summary>
12
+ public class RegisterForAddParticipantChatMapping : ScriptBase, IMapping
13
+ {
14
+ public async Task<ScriptResponse> InputHandler(WorkflowTask task, ScriptContext context)
15
+ {
16
+ var httpTask = task as HttpTask;
17
+ if (httpTask == null)
18
+ throw new InvalidOperationException("Task must be an HttpTask");
19
+
20
+ var data = context.Instance?.Data;
21
+ var newUserId = GetString(data, "newUserId");
22
+ if (string.IsNullOrWhiteSpace(newUserId))
23
+ return new ScriptResponse();
24
+
25
+ var secretName = GetConfigValue("DAPR_SECRET_STORE_NAME");
26
+ if (string.IsNullOrWhiteSpace(secretName))
27
+ throw new InvalidOperationException("DAPR_SECRET_STORE_NAME configuration is required");
28
+
29
+ var matrixBaseUrl = await GetSecretAsync(secretName, "workflow-secret", "MatrixBaseUrl");
30
+ if (string.IsNullOrWhiteSpace(matrixBaseUrl))
31
+ throw new InvalidOperationException("MatrixBaseUrl secret is required");
32
+
33
+ var synapsePassword = await GetSecretAsync(secretName, "workflow-secret", "SynapsePassword");
34
+ if (string.IsNullOrWhiteSpace(synapsePassword))
35
+ throw new InvalidOperationException("SynapsePassword secret is required");
36
+
37
+ var fullUrl = matrixBaseUrl.TrimEnd('/') + "/_matrix/client/v3/register";
38
+ httpTask.SetUrl(fullUrl);
39
+
40
+ httpTask.SetHeaders(new Dictionary<string, string>
41
+ {
42
+ ["Content-Type"] = "application/json",
43
+ ["Accept"] = "application/json"
44
+ });
45
+
46
+ httpTask.SetBody(new
47
+ {
48
+ auth = new { type = "m.login.dummy" },
49
+ username = newUserId.Trim(),
50
+ password = synapsePassword
51
+ });
52
+ return new ScriptResponse();
53
+ }
54
+
55
+ public Task<ScriptResponse> OutputHandler(ScriptContext context)
56
+ {
57
+ return Task.FromResult(new ScriptResponse());
58
+ }
59
+
60
+ private string GetString(dynamic obj, string name)
61
+ {
62
+ if (obj == null) return null;
63
+ try
64
+ {
65
+ if (HasProperty(obj, name))
66
+ {
67
+ var v = GetPropertyValue(obj, name);
68
+ return v?.ToString();
69
+ }
70
+ }
71
+ catch { }
72
+ return null;
73
+ }
74
+ }
@@ -0,0 +1,52 @@
1
+ using System;
2
+ using System.Threading.Tasks;
3
+ using BBT.Workflow.Scripting;
4
+ using BBT.Workflow.Definitions;
5
+
6
+ /// <summary>
7
+ /// Mapping for start-register-matrix-user StartTask (Type 11) in chat-room workflow.
8
+ /// Starts register-matrix-user flow with matrixUsername = "u" + data.user.
9
+ /// </summary>
10
+ public class RegisterForChatRoomMapping : ScriptBase, IMapping
11
+ {
12
+ public Task<ScriptResponse> InputHandler(WorkflowTask task, ScriptContext context)
13
+ {
14
+ var startTask = task as StartTask;
15
+ if (startTask == null)
16
+ throw new InvalidOperationException("Task must be a StartTask");
17
+
18
+ var data = context.Instance?.Data;
19
+ var user = GetString(data, "user");
20
+ if (string.IsNullOrWhiteSpace(user))
21
+ throw new InvalidOperationException("Cannot determine register user: data.user is missing");
22
+
23
+ var matrixUsername = "u" + user;
24
+
25
+ startTask.SetDomain("morph-touch");
26
+ startTask.SetFlow("register-matrix-user");
27
+ startTask.SetSync(true);
28
+ startTask.SetBody(new { matrixUsername });
29
+
30
+ return Task.FromResult(new ScriptResponse());
31
+ }
32
+
33
+ public Task<ScriptResponse> OutputHandler(ScriptContext context)
34
+ {
35
+ return Task.FromResult(new ScriptResponse());
36
+ }
37
+
38
+ private string GetString(dynamic obj, string name)
39
+ {
40
+ if (obj == null) return null;
41
+ try
42
+ {
43
+ if (HasProperty(obj, name))
44
+ {
45
+ var v = GetPropertyValue(obj, name);
46
+ return v?.ToString();
47
+ }
48
+ }
49
+ catch { }
50
+ return null;
51
+ }
52
+ }
@@ -0,0 +1,63 @@
1
+ using System;
2
+ using System.Threading.Tasks;
3
+ using BBT.Workflow.Scripting;
4
+ using BBT.Workflow.Definitions;
5
+
6
+ /// <summary>
7
+ /// Mapping for start-register-matrix-user StartTask (Type 11) before join-user-to-room.
8
+ /// Starts register-matrix-user flow with matrixUsername from pendingJoinUserId / newAdvisorId / advisorId.
9
+ /// </summary>
10
+ public class RegisterForJoinUserToRoomMapping : ScriptBase, IMapping
11
+ {
12
+ public Task<ScriptResponse> InputHandler(WorkflowTask task, ScriptContext context)
13
+ {
14
+ var startTask = task as StartTask;
15
+ if (startTask == null)
16
+ throw new InvalidOperationException("Task must be a StartTask");
17
+
18
+ var data = context.Instance?.Data;
19
+
20
+ var joinUser = GetString(data, "pendingJoinUserId");
21
+ if (string.IsNullOrWhiteSpace(joinUser))
22
+ joinUser = GetString(data, "newAdvisorId");
23
+ if (string.IsNullOrWhiteSpace(joinUser))
24
+ joinUser = GetString(data, "advisorId");
25
+
26
+ if (string.IsNullOrWhiteSpace(joinUser))
27
+ return Task.FromResult(new ScriptResponse());
28
+
29
+ var matrixUsername = joinUser.Trim();
30
+ if (matrixUsername.StartsWith("@"))
31
+ {
32
+ var colonIdx = matrixUsername.IndexOf(':');
33
+ matrixUsername = colonIdx > 0 ? matrixUsername.Substring(1, colonIdx - 1) : matrixUsername.Substring(1);
34
+ }
35
+
36
+ startTask.SetDomain("morph-touch");
37
+ startTask.SetFlow("register-matrix-user");
38
+ startTask.SetSync(true);
39
+ startTask.SetBody(new { matrixUsername });
40
+
41
+ return Task.FromResult(new ScriptResponse());
42
+ }
43
+
44
+ public Task<ScriptResponse> OutputHandler(ScriptContext context)
45
+ {
46
+ return Task.FromResult(new ScriptResponse());
47
+ }
48
+
49
+ private string GetString(dynamic obj, string name)
50
+ {
51
+ if (obj == null) return null;
52
+ try
53
+ {
54
+ if (HasProperty(obj, name))
55
+ {
56
+ var v = GetPropertyValue(obj, name);
57
+ return v?.ToString();
58
+ }
59
+ }
60
+ catch { }
61
+ return null;
62
+ }
63
+ }