feat: LeanEngine
parent
e5b9f29575
commit
aad4e7cc47
|
@ -0,0 +1,31 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace LeanCloud.Engine {
|
||||||
|
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
|
||||||
|
public class LCEngineFunctionAttribute : Attribute {
|
||||||
|
public string FunctionName {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LCEngineFunctionAttribute(string funcName) {
|
||||||
|
if (string.IsNullOrEmpty(funcName)) {
|
||||||
|
throw new ArgumentNullException(nameof(funcName));
|
||||||
|
}
|
||||||
|
FunctionName = funcName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)]
|
||||||
|
public class LCEngineFunctionParameterAttribute : Attribute {
|
||||||
|
public string ParameterName {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LCEngineFunctionParameterAttribute(string paramName) {
|
||||||
|
if (string.IsNullOrEmpty(paramName)) {
|
||||||
|
throw new ArgumentNullException(nameof(paramName));
|
||||||
|
}
|
||||||
|
ParameterName = paramName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace LeanCloud.Engine {
|
||||||
|
public enum LCEngineObjectHookType {
|
||||||
|
BeforeSave,
|
||||||
|
AfterSave,
|
||||||
|
BeforeUpdate,
|
||||||
|
AfterUpdate,
|
||||||
|
BeforeDelete,
|
||||||
|
AfterDelete
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LCEngineObjectHookAttribute : Attribute {
|
||||||
|
public string ClassName {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LCEngineObjectHookType HookType {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LCEngineObjectHookAttribute(string className, LCEngineObjectHookType hookType) {
|
||||||
|
ClassName = className;
|
||||||
|
HookType = hookType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace LeanCloud.Engine {
|
||||||
|
public enum LCEngineRealtimeHookType {
|
||||||
|
// 消息
|
||||||
|
MessageReceived,
|
||||||
|
MessageSent,
|
||||||
|
MessageUpdate,
|
||||||
|
ReceiversOffline,
|
||||||
|
// 对话
|
||||||
|
ConversationStart,
|
||||||
|
ConversationStarted,
|
||||||
|
ConversationAdd,
|
||||||
|
ConversationAdded,
|
||||||
|
ConversationRemove,
|
||||||
|
ConversationRemoved,
|
||||||
|
ConversationUpdate,
|
||||||
|
// 客户端
|
||||||
|
ClientOnline,
|
||||||
|
ClientOffline,
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LCEngineRealtimeHookAttribute : Attribute {
|
||||||
|
public LCEngineRealtimeHookType HookType {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LCEngineRealtimeHookAttribute(LCEngineRealtimeHookType hookType) {
|
||||||
|
HookType = hookType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace LeanCloud.Engine {
|
||||||
|
public enum LCEngineUserHookType {
|
||||||
|
SMS,
|
||||||
|
Email,
|
||||||
|
OnLogin
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LCEngineUserHookAttribute : Attribute {
|
||||||
|
public LCEngineUserHookType HookType {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LCEngineUserHookAttribute(LCEngineUserHookType hookType) {
|
||||||
|
HookType = hookType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Common\Common\Common.csproj" />
|
||||||
|
<ProjectReference Include="..\Storage\Storage\Storage.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
|
@ -0,0 +1,72 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Text.Json;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using LeanCloud.Storage.Internal.Object;
|
||||||
|
using LeanCloud.Storage;
|
||||||
|
|
||||||
|
namespace LeanCloud.Engine {
|
||||||
|
public class LCClassHookHandler {
|
||||||
|
private static Dictionary<string, MethodInfo> ClassHooks => LCEngine.ClassHooks;
|
||||||
|
|
||||||
|
public static void Hello() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<object> HandleClassHook(string className, string hookName, HttpRequest request, JsonElement body) {
|
||||||
|
LCLogger.Debug($"Hook: {className}#{hookName}");
|
||||||
|
LCLogger.Debug(body.ToString());
|
||||||
|
|
||||||
|
LCEngine.CheckHookKey(request);
|
||||||
|
|
||||||
|
string classHookName = GetClassHookName(className, hookName);
|
||||||
|
if (ClassHooks.TryGetValue(classHookName, out MethodInfo mi)) {
|
||||||
|
Dictionary<string, object> dict = LCEngine.Decode(body);
|
||||||
|
|
||||||
|
LCObjectData objectData = LCObjectData.Decode(dict["object"] as Dictionary<string, object>);
|
||||||
|
objectData.ClassName = className;
|
||||||
|
LCObject obj = LCObject.Create(className);
|
||||||
|
obj.Merge(objectData);
|
||||||
|
|
||||||
|
LCUser user = null;
|
||||||
|
if (dict.TryGetValue("user", out object userObj) &&
|
||||||
|
userObj != null) {
|
||||||
|
user = new LCUser();
|
||||||
|
user.Merge(LCObjectData.Decode(userObj as Dictionary<string, object>));
|
||||||
|
}
|
||||||
|
|
||||||
|
LCClassHookRequest req = new LCClassHookRequest {
|
||||||
|
Object = obj,
|
||||||
|
CurrentUser = user
|
||||||
|
};
|
||||||
|
|
||||||
|
LCObject result = await LCEngine.Invoke(mi, req) as LCObject;
|
||||||
|
if (result != null) {
|
||||||
|
return LCCloud.Encode(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetClassHookName(string className, string hookName) {
|
||||||
|
switch (hookName) {
|
||||||
|
case "beforeSave":
|
||||||
|
return $"__before_save_for_{className}";
|
||||||
|
case "afterSave":
|
||||||
|
return $"__after_save_for_{className}";
|
||||||
|
case "beforeUpdate":
|
||||||
|
return $"__before_update_for_{className}";
|
||||||
|
case "afterUpdate":
|
||||||
|
return $"__after_update_for_{className}";
|
||||||
|
case "beforeDelete":
|
||||||
|
return $"__before_delete_for_{className}";
|
||||||
|
case "afterDelete":
|
||||||
|
return $"__after_delete_for_{className}";
|
||||||
|
default:
|
||||||
|
throw new Exception($"Error hook name: {hookName}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Text.Json;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.Primitives;
|
||||||
|
using LeanCloud.Storage.Internal.Codec;
|
||||||
|
using LeanCloud.Storage;
|
||||||
|
|
||||||
|
namespace LeanCloud.Engine {
|
||||||
|
public class LCFunctionHandler {
|
||||||
|
private static Dictionary<string, MethodInfo> Functions => LCEngine.Functions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 云函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="funcName"></param>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
/// <param name="body"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static async Task<object> HandleRun(string funcName, HttpRequest request, JsonElement body) {
|
||||||
|
LCLogger.Debug($"Run: {funcName}");
|
||||||
|
LCLogger.Debug(body.ToString());
|
||||||
|
|
||||||
|
if (Functions.TryGetValue(funcName, out MethodInfo mi)) {
|
||||||
|
LCUser currentUser = null;
|
||||||
|
if (request.Headers.TryGetValue("x-lc-session", out StringValues session)) {
|
||||||
|
currentUser = await LCUser.BecomeWithSessionToken(session);
|
||||||
|
}
|
||||||
|
LCCloudFunctionRequest req = new LCCloudFunctionRequest {
|
||||||
|
Meta = new LCCloudFunctionRequestMeta {
|
||||||
|
RemoteAddress = LCEngine.GetIP(request)
|
||||||
|
},
|
||||||
|
Params = LCEngine.Decode(body),
|
||||||
|
SessionToken = session.ToString(),
|
||||||
|
User = currentUser
|
||||||
|
};
|
||||||
|
object result = await LCEngine.Invoke(mi, req);
|
||||||
|
if (result != null) {
|
||||||
|
return new Dictionary<string, object> {
|
||||||
|
{ "result", result }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// RPC
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="funcName"></param>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
/// <param name="body"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static async Task<object> HandleRPC(string funcName, HttpRequest request, JsonElement body) {
|
||||||
|
LCLogger.Debug($"RPC: {funcName}");
|
||||||
|
LCLogger.Debug(body.ToString());
|
||||||
|
|
||||||
|
if (Functions.TryGetValue(funcName, out MethodInfo mi)) {
|
||||||
|
LCUser currentUser = null;
|
||||||
|
if (request.Headers.TryGetValue("x-lc-session", out StringValues session)) {
|
||||||
|
currentUser = await LCUser.BecomeWithSessionToken(session);
|
||||||
|
}
|
||||||
|
LCCloudRPCRequest req = new LCCloudRPCRequest {
|
||||||
|
Meta = new LCCloudFunctionRequestMeta {
|
||||||
|
RemoteAddress = LCEngine.GetIP(request)
|
||||||
|
},
|
||||||
|
Params = LCDecoder.Decode(LCEngine.Decode(body)),
|
||||||
|
SessionToken = session.ToString(),
|
||||||
|
User = currentUser
|
||||||
|
};
|
||||||
|
object result = await LCEngine.Invoke(mi, req);
|
||||||
|
if (result != null) {
|
||||||
|
return new Dictionary<string, object> {
|
||||||
|
{ "result", LCCloud.Encode(result) }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace LeanCloud.Engine {
|
||||||
|
public class LCPingHandler {
|
||||||
|
public static object HandlePing() {
|
||||||
|
LCLogger.Debug("Ping ~~~");
|
||||||
|
return new Dictionary<string, string> {
|
||||||
|
{ "runtime", "dotnet" },
|
||||||
|
{ "version", LCApplication.SDKVersion }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Text.Json;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using LeanCloud.Storage.Internal.Object;
|
||||||
|
using LeanCloud.Storage;
|
||||||
|
|
||||||
|
namespace LeanCloud.Engine {
|
||||||
|
public class LCUserHookHandler {
|
||||||
|
private static Dictionary<string, MethodInfo> UserHooks => LCEngine.UserHooks;
|
||||||
|
|
||||||
|
public static async Task<object> HandleVerifiedSMS(HttpRequest request, JsonElement body) {
|
||||||
|
LCLogger.Debug(LCEngine.OnSMSVerified);
|
||||||
|
LCLogger.Debug(body.ToString());
|
||||||
|
|
||||||
|
LCEngine.CheckHookKey(request);
|
||||||
|
|
||||||
|
if (UserHooks.TryGetValue(LCEngine.OnSMSVerified, out MethodInfo mi)) {
|
||||||
|
Dictionary<string, object> dict = LCEngine.Decode(body);
|
||||||
|
return await Invoke(mi, dict);
|
||||||
|
}
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<object> HandleVerifiedEmail(HttpRequest request, JsonElement body) {
|
||||||
|
LCLogger.Debug(LCEngine.OnEmailVerified);
|
||||||
|
LCLogger.Debug(body.ToString());
|
||||||
|
|
||||||
|
LCEngine.CheckHookKey(request);
|
||||||
|
|
||||||
|
if (UserHooks.TryGetValue(LCEngine.OnEmailVerified, out MethodInfo mi)) {
|
||||||
|
Dictionary<string, object> dict = LCEngine.Decode(body);
|
||||||
|
return await Invoke(mi, dict);
|
||||||
|
}
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<object> HandleLogin(HttpRequest request, JsonElement body) {
|
||||||
|
LCLogger.Debug(LCEngine.OnLogin);
|
||||||
|
LCLogger.Debug(body.ToString());
|
||||||
|
|
||||||
|
LCEngine.CheckHookKey(request);
|
||||||
|
|
||||||
|
if (UserHooks.TryGetValue(LCEngine.OnLogin, out MethodInfo mi)) {
|
||||||
|
Dictionary<string, object> dict = LCEngine.Decode(body);
|
||||||
|
return await Invoke(mi, dict);
|
||||||
|
}
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<object> Invoke(MethodInfo mi, Dictionary<string, object> dict) {
|
||||||
|
LCObjectData objectData = LCObjectData.Decode(dict["object"] as Dictionary<string, object>);
|
||||||
|
objectData.ClassName = "_User";
|
||||||
|
|
||||||
|
LCObject obj = LCObject.Create("_User");
|
||||||
|
obj.Merge(objectData);
|
||||||
|
|
||||||
|
LCUserHookRequest req = new LCUserHookRequest {
|
||||||
|
CurrentUser = obj as LCUser
|
||||||
|
};
|
||||||
|
|
||||||
|
return await LCEngine.Invoke(mi, req) as LCObject;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,227 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Text.Json;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Microsoft.Extensions.Primitives;
|
||||||
|
using LeanCloud.Common;
|
||||||
|
|
||||||
|
namespace LeanCloud.Engine {
|
||||||
|
public class LCEngine {
|
||||||
|
const string LCMasterKeyName = "x-avoscloud-master-key";
|
||||||
|
const string LCHookKeyName = "x-lc-hook-key";
|
||||||
|
|
||||||
|
const string BeforeSave = "__before_save_for_";
|
||||||
|
const string AfterSave = "__after_save_for_";
|
||||||
|
const string BeforeUpdate = "__before_update_for_";
|
||||||
|
const string AfterUpdate = "__after_update_for_";
|
||||||
|
const string BeforeDelete = "__before_delete_for_";
|
||||||
|
const string AfterDelete = "__after_delete_for_";
|
||||||
|
|
||||||
|
internal const string OnSMSVerified = "__on_verified_sms";
|
||||||
|
internal const string OnEmailVerified = "__on_verified_email";
|
||||||
|
internal const string OnLogin = "__on_login__User";
|
||||||
|
|
||||||
|
const string ClientOnline = "_clientOnline";
|
||||||
|
const string ClientOffline = "_clientOffline";
|
||||||
|
|
||||||
|
const string MessageSent = "_messageSent";
|
||||||
|
const string MessageReceived = "_messageReceived";
|
||||||
|
const string ReceiversOffline = "_receiversOffline";
|
||||||
|
const string MessageUpdate = "_messageUpdate";
|
||||||
|
|
||||||
|
const string ConversationStart = "_conversationStart";
|
||||||
|
const string ConversationStarted = "_conversationStarted";
|
||||||
|
const string ConversationAdd = "_conversationAdd";
|
||||||
|
const string ConversationAdded = "_conversationAdded";
|
||||||
|
const string ConversationRemove = "_conversationRemove";
|
||||||
|
const string ConversationRemoved = "_conversationRemoved";
|
||||||
|
const string ConversationUpdate = "_conversationUpdate";
|
||||||
|
|
||||||
|
public static Dictionary<string, MethodInfo> Functions = new Dictionary<string, MethodInfo>();
|
||||||
|
public static Dictionary<string, MethodInfo> ClassHooks = new Dictionary<string, MethodInfo>();
|
||||||
|
public static Dictionary<string, MethodInfo> UserHooks = new Dictionary<string, MethodInfo>();
|
||||||
|
|
||||||
|
public static void Initialize() {
|
||||||
|
// 获取环境变量
|
||||||
|
LCLogger.Debug("-------------------------------------------------");
|
||||||
|
PrintEnvironmentVar("LEANCLOUD_APP_ID");
|
||||||
|
PrintEnvironmentVar("LEANCLOUD_APP_KEY");
|
||||||
|
PrintEnvironmentVar("LEANCLOUD_APP_MASTER_KEY");
|
||||||
|
PrintEnvironmentVar("LEANCLOUD_APP_HOOK_KEY");
|
||||||
|
PrintEnvironmentVar("LEANCLOUD_API_SERVER");
|
||||||
|
PrintEnvironmentVar("LEANCLOUD_APP_PROD");
|
||||||
|
PrintEnvironmentVar("LEANCLOUD_APP_ENV");
|
||||||
|
PrintEnvironmentVar("LEANCLOUD_APP_INSTANCE");
|
||||||
|
PrintEnvironmentVar("LEANCLOUD_REGION");
|
||||||
|
PrintEnvironmentVar("LEANCLOUD_APP_ID");
|
||||||
|
PrintEnvironmentVar("LEANCLOUD_APP_DOMAIN");
|
||||||
|
PrintEnvironmentVar("LEANCLOUD_APP_PORT");
|
||||||
|
LCLogger.Debug("-------------------------------------------------");
|
||||||
|
|
||||||
|
LCApplication.Initialize(Environment.GetEnvironmentVariable("LEANCLOUD_APP_ID"),
|
||||||
|
Environment.GetEnvironmentVariable("LEANCLOUD_APP_KEY"),
|
||||||
|
Environment.GetEnvironmentVariable("LEANCLOUD_API_SERVER"));
|
||||||
|
|
||||||
|
Assembly assembly = Assembly.GetCallingAssembly();
|
||||||
|
ClassHooks = assembly.GetTypes()
|
||||||
|
.SelectMany(t => t.GetMethods())
|
||||||
|
.Where(m => m.GetCustomAttribute<LCEngineObjectHookAttribute>() != null)
|
||||||
|
.ToDictionary(mi => {
|
||||||
|
LCEngineObjectHookAttribute attr = mi.GetCustomAttribute<LCEngineObjectHookAttribute>();
|
||||||
|
switch (attr.HookType) {
|
||||||
|
case LCEngineObjectHookType.BeforeSave:
|
||||||
|
return $"{BeforeSave}{attr.ClassName}";
|
||||||
|
case LCEngineObjectHookType.AfterSave:
|
||||||
|
return $"{AfterSave}{attr.ClassName}";
|
||||||
|
case LCEngineObjectHookType.BeforeUpdate:
|
||||||
|
return $"{BeforeUpdate}{attr.ClassName}";
|
||||||
|
case LCEngineObjectHookType.AfterUpdate:
|
||||||
|
return $"{AfterUpdate}{attr.ClassName}";
|
||||||
|
case LCEngineObjectHookType.BeforeDelete:
|
||||||
|
return $"{BeforeDelete}{attr.ClassName}";
|
||||||
|
case LCEngineObjectHookType.AfterDelete:
|
||||||
|
return $"{AfterDelete}{attr.ClassName}";
|
||||||
|
default:
|
||||||
|
throw new Exception($"Error hook type: {attr.HookType}");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
UserHooks = assembly.GetTypes()
|
||||||
|
.SelectMany(t => t.GetMethods())
|
||||||
|
.Where(m => m.GetCustomAttribute<LCEngineUserHookAttribute>() != null)
|
||||||
|
.ToDictionary(mi => {
|
||||||
|
LCEngineUserHookAttribute attr = mi.GetCustomAttribute<LCEngineUserHookAttribute>();
|
||||||
|
switch (attr.HookType) {
|
||||||
|
case LCEngineUserHookType.SMS:
|
||||||
|
return OnSMSVerified;
|
||||||
|
case LCEngineUserHookType.Email:
|
||||||
|
return OnEmailVerified;
|
||||||
|
case LCEngineUserHookType.OnLogin:
|
||||||
|
return OnLogin;
|
||||||
|
default:
|
||||||
|
throw new Exception($"Error hook type: {attr.HookType}");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Functions = assembly.GetTypes()
|
||||||
|
.SelectMany(t => t.GetMethods())
|
||||||
|
.Where(m => m.GetCustomAttribute<LCEngineFunctionAttribute>() != null)
|
||||||
|
.ToDictionary(mi => mi.GetCustomAttribute<LCEngineFunctionAttribute>().FunctionName);
|
||||||
|
|
||||||
|
assembly.GetTypes()
|
||||||
|
.SelectMany(t => t.GetMethods())
|
||||||
|
.Where(m => m.GetCustomAttribute<LCEngineRealtimeHookAttribute>() != null)
|
||||||
|
.ToDictionary(mi => {
|
||||||
|
LCEngineRealtimeHookAttribute attr = mi.GetCustomAttribute<LCEngineRealtimeHookAttribute>();
|
||||||
|
switch (attr.HookType) {
|
||||||
|
case LCEngineRealtimeHookType.ClientOnline:
|
||||||
|
return ClientOnline;
|
||||||
|
case LCEngineRealtimeHookType.ClientOffline:
|
||||||
|
return ClientOffline;
|
||||||
|
case LCEngineRealtimeHookType.MessageSent:
|
||||||
|
return MessageSent;
|
||||||
|
case LCEngineRealtimeHookType.MessageReceived:
|
||||||
|
return MessageReceived;
|
||||||
|
case LCEngineRealtimeHookType.ReceiversOffline:
|
||||||
|
return ReceiversOffline;
|
||||||
|
case LCEngineRealtimeHookType.MessageUpdate:
|
||||||
|
return MessageUpdate;
|
||||||
|
case LCEngineRealtimeHookType.ConversationStart:
|
||||||
|
return ConversationStart;
|
||||||
|
case LCEngineRealtimeHookType.ConversationStarted:
|
||||||
|
return ConversationStarted;
|
||||||
|
case LCEngineRealtimeHookType.ConversationAdd:
|
||||||
|
return ConversationAdd;
|
||||||
|
case LCEngineRealtimeHookType.ConversationAdded:
|
||||||
|
return ConversationAdded;
|
||||||
|
case LCEngineRealtimeHookType.ConversationRemove:
|
||||||
|
return ConversationRemove;
|
||||||
|
case LCEngineRealtimeHookType.ConversationRemoved:
|
||||||
|
return ConversationRemoved;
|
||||||
|
case LCEngineRealtimeHookType.ConversationUpdate:
|
||||||
|
return ConversationUpdate;
|
||||||
|
default:
|
||||||
|
throw new Exception($"Error hook type: {attr.HookType}");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.ToList()
|
||||||
|
.ForEach(item => {
|
||||||
|
Functions.TryAdd(item.Key, item.Value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void PrintEnvironmentVar(string key) {
|
||||||
|
LCLogger.Debug($"{key} : {Environment.GetEnvironmentVariable(key)}");
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static async Task<object> Invoke(MethodInfo mi, object request) {
|
||||||
|
try {
|
||||||
|
object[] ps = new object[] { request };
|
||||||
|
if (mi.ReturnType == typeof(Task) ||
|
||||||
|
(mi.ReturnType.IsGenericType && mi.ReturnType.GetGenericTypeDefinition() == typeof(Task<>))) {
|
||||||
|
Task task = mi.Invoke(null, ps) as Task;
|
||||||
|
await task;
|
||||||
|
return task.GetType().GetProperty("Result")?.GetValue(task);
|
||||||
|
}
|
||||||
|
return mi.Invoke(null, ps);
|
||||||
|
} catch (TargetInvocationException e) {
|
||||||
|
throw e.InnerException;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static Dictionary<string, object> Decode(JsonElement jsonElement) {
|
||||||
|
string json = System.Text.Json.JsonSerializer.Serialize(jsonElement);
|
||||||
|
Dictionary<string, object> dict = JsonConvert.DeserializeObject<Dictionary<string, object>>(json,
|
||||||
|
LCJsonConverter.Default);
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string GetIP(HttpRequest request) {
|
||||||
|
if (request.Headers.TryGetValue("x-real-ip", out StringValues ip)) {
|
||||||
|
return ip.ToString();
|
||||||
|
}
|
||||||
|
if (request.Headers.TryGetValue("x-forwarded-for", out StringValues forward)) {
|
||||||
|
return forward.ToString();
|
||||||
|
}
|
||||||
|
return request.HttpContext.Connection.RemoteIpAddress.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void CheckMasterKey(HttpRequest request) {
|
||||||
|
if (!request.Headers.TryGetValue(LCMasterKeyName, out StringValues masterKey)) {
|
||||||
|
throw new Exception("No master key");
|
||||||
|
}
|
||||||
|
if (!masterKey.Equals(Environment.GetEnvironmentVariable("LEANCLOUD_APP_MASTER_KEY"))) {
|
||||||
|
throw new Exception("Mismatch master key");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void CheckHookKey(HttpRequest request) {
|
||||||
|
if (!request.Headers.TryGetValue(LCHookKeyName, out StringValues hookKey)) {
|
||||||
|
throw new Exception("No hook key");
|
||||||
|
}
|
||||||
|
if (!hookKey.Equals(Environment.GetEnvironmentVariable("LEANCLOUD_APP_HOOK_KEY"))) {
|
||||||
|
throw new Exception("Mismatch hook key");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static object GetFunctions(HttpRequest request) {
|
||||||
|
CheckMasterKey(request);
|
||||||
|
|
||||||
|
List<string> functions = new List<string>();
|
||||||
|
functions.AddRange(Functions.Keys);
|
||||||
|
functions.AddRange(ClassHooks.Keys);
|
||||||
|
functions.AddRange(UserHooks.Keys);
|
||||||
|
foreach (string func in functions) {
|
||||||
|
LCLogger.Debug(func);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Dictionary<string, List<string>> {
|
||||||
|
{ "result", functions }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
using LeanCloud.Storage;
|
||||||
|
|
||||||
|
namespace LeanCloud.Engine {
|
||||||
|
public class LCClassHookRequest {
|
||||||
|
public LCObject Object {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LCUser CurrentUser {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using LeanCloud.Storage;
|
||||||
|
|
||||||
|
namespace LeanCloud.Engine {
|
||||||
|
public class LCCloudFunctionRequestMeta {
|
||||||
|
public string RemoteAddress {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LCCloudFunctionRequest {
|
||||||
|
public LCCloudFunctionRequestMeta Meta {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dictionary<string, object> Params {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LCUser User {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string SessionToken {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
using LeanCloud.Storage;
|
||||||
|
|
||||||
|
namespace LeanCloud.Engine {
|
||||||
|
public class LCCloudRPCRequest {
|
||||||
|
public LCCloudFunctionRequestMeta Meta {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Params {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LCUser User {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string SessionToken {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
using LeanCloud.Storage;
|
||||||
|
|
||||||
|
namespace LeanCloud.Engine {
|
||||||
|
public class LCUserHookRequest {
|
||||||
|
public LCUser CurrentUser {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue