submodule对gitea不管用,所以直接拉了一份拉格兰
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Ability;
|
||||
|
||||
[Operation("can_send_image")]
|
||||
public class CanSendImage : IOperation
|
||||
{
|
||||
public Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload) =>
|
||||
Task.FromResult(new OneBotResult(new JsonObject { { "yes", Constant.CanSendImage } }, 0, "ok"));
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Ability;
|
||||
|
||||
[Operation("can_send_record")]
|
||||
public class CanSendRecord : IOperation
|
||||
{
|
||||
public Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload) =>
|
||||
Task.FromResult(new OneBotResult(new JsonObject { { "yes", Constant.CanSendRecord } }, 0, "ok"));
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.Core.Message.Entity;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Message.Entity;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Ability;
|
||||
|
||||
[Operation("upload_image")]
|
||||
public class UploadImageOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload?["file"]?.ToString() is { } file && CommonResolver.ResolveStream(file) is { } stream)
|
||||
{
|
||||
var entity = new ImageEntity(stream);
|
||||
var url = await context.UploadImage(entity);
|
||||
return new OneBotResult(url, 0, "ok");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.Buffers;
|
||||
using System.Buffers.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
public class AutosizeConverter : JsonConverter<bool>
|
||||
{
|
||||
public override bool Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
return reader.TokenType switch
|
||||
{
|
||||
JsonTokenType.True => true,
|
||||
JsonTokenType.False => false,
|
||||
JsonTokenType.String when Utf8Parser.TryParse(reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan, out bool value, out _) => value,
|
||||
JsonTokenType.String when Utf8Parser.TryParse(reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan, out int intValue, out _) => intValue != 0,
|
||||
JsonTokenType.Number when reader.TryGetInt32(out int val) => Convert.ToBoolean(val),
|
||||
_ => throw new JsonException()
|
||||
};
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, bool value, JsonSerializerOptions options) => writer.WriteBooleanValue(value);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.Buffers;
|
||||
using System.Buffers.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
public class BooleanConverter : JsonConverter<bool>
|
||||
{
|
||||
public override bool Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
return reader.TokenType switch
|
||||
{
|
||||
JsonTokenType.True => true,
|
||||
JsonTokenType.False => false,
|
||||
JsonTokenType.String when Utf8Parser.TryParse(reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan, out bool value, out _) => value,
|
||||
_ => throw new JsonException()
|
||||
};
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, bool value, JsonSerializerOptions options)
|
||||
{
|
||||
writer.WriteBooleanValue(value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
public class ForwardConverter : JsonConverter<int>
|
||||
{
|
||||
public override int Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
return reader.TokenType switch
|
||||
{
|
||||
JsonTokenType.True => 1,
|
||||
JsonTokenType.False => 0,
|
||||
JsonTokenType.Number when reader.TryGetInt32(out int intValue) => intValue,
|
||||
_ => throw new JsonException()
|
||||
};
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, int value, JsonSerializerOptions options) => writer.WriteNumberValue(value);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
public class NullIfEmptyConverter<T> : JsonConverter<T> where T : class
|
||||
{
|
||||
public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
return reader.TokenType switch
|
||||
{
|
||||
JsonTokenType.String when reader.ValueSpan.Length == 0 => null,
|
||||
JsonTokenType.StartObject => JsonSerializer.Deserialize<T>(ref reader, options),
|
||||
_ => throw new JsonException()
|
||||
};
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, T? value, JsonSerializerOptions options) => JsonSerializer.Serialize(writer, value, options);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
public static class SerializerOptions
|
||||
{
|
||||
public static JsonSerializerOptions DefaultOptions => new()
|
||||
{
|
||||
Converters = { new BooleanConverter() },
|
||||
NumberHandling = JsonNumberHandling.AllowReadingFromString
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Entity;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Entity.Action.Response;
|
||||
using Lagrange.OneBot.Core.Entity.File;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
using Lagrange.OneBot.Utility;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.File;
|
||||
|
||||
[Operation("get_group_file_url")]
|
||||
public class GetGroupFileUrlOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotGetFileUrl>(SerializerOptions.DefaultOptions) is { } url)
|
||||
{
|
||||
string raw = await context.FetchGroupFSDownload(url.GroupId, url.FileId);
|
||||
return new OneBotResult(new JsonObject { { "url", raw } }, 0, "ok");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
|
||||
[Operation("get_group_root_files")]
|
||||
[Operation("get_group_files_by_folder")]
|
||||
public class GetGroupRootFilesOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotGetFiles>(SerializerOptions.DefaultOptions) is { } file)
|
||||
{
|
||||
var entries = await context.FetchGroupFSList(file.GroupId, file.FolderId ?? "/");
|
||||
var files = new List<OneBotFile>();
|
||||
var folders = new List<OneBotFolder>();
|
||||
|
||||
foreach (var entry in entries)
|
||||
{
|
||||
switch (entry)
|
||||
{
|
||||
case BotFileEntry fileEntry:
|
||||
{
|
||||
var members = await context.FetchMembers(file.GroupId);
|
||||
var member = members.FirstOrDefault(x => x.Uin == fileEntry.UploaderUin);
|
||||
files.Add(new OneBotFile
|
||||
{
|
||||
GroupId = file.GroupId,
|
||||
FileId = fileEntry.FileId,
|
||||
FileName = fileEntry.FileName,
|
||||
BusId = 0,
|
||||
FileSize = fileEntry.FileSize,
|
||||
UploadTime = fileEntry.UploadedTime.ToTimestamp(),
|
||||
DeadTime = fileEntry.ExpireTime.ToTimestamp(),
|
||||
ModifyTime = fileEntry.ModifiedTime.ToTimestamp(),
|
||||
DownloadTimes = fileEntry.DownloadedTimes,
|
||||
Uploader = fileEntry.UploaderUin,
|
||||
UploaderName = member?.MemberName ?? string.Empty
|
||||
});
|
||||
break;
|
||||
}
|
||||
case BotFolderEntry folderEntry:
|
||||
{
|
||||
var members = await context.FetchMembers(file.GroupId);
|
||||
var member = members.FirstOrDefault(x => x.Uin == folderEntry.CreatorUin);
|
||||
folders.Add(new OneBotFolder
|
||||
{
|
||||
GroupId = file.GroupId,
|
||||
FolderId = folderEntry.FolderId,
|
||||
FolderName = folderEntry.FolderName,
|
||||
CreateTime = folderEntry.CreateTime.ToTimestamp(),
|
||||
Creator = folderEntry.CreatorUin,
|
||||
CreatorName = member?.MemberName ?? string.Empty,
|
||||
TotalFileCount = folderEntry.TotalFileCount
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new OneBotResult(new OneBotGetFilesResponse(files, folders), 0, "ok");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
|
||||
[Operation("move_group_file")]
|
||||
public class MoveGroupFileOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotMoveFile>(SerializerOptions.DefaultOptions) is { } file)
|
||||
{
|
||||
var res = await context.GroupFSMove(file.GroupId, file.FileId, file.ParentDirectory, file.TargetDirectory);
|
||||
return new OneBotResult(new JsonObject { { "msg", res.Item2 } }, res.Item1, res.Item1 == 0 ? "ok" : "failed");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
|
||||
[Operation("delete_group_file")]
|
||||
public class DeleteGroupFileOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotDeleteFile>(SerializerOptions.DefaultOptions) is { } file)
|
||||
{
|
||||
var res = await context.GroupFSDelete(file.GroupId, file.FileId);
|
||||
return new OneBotResult(new JsonObject { { "msg", res.Item2 } }, res.Item1, res.Item1 == 0 ? "ok" : "failed");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
|
||||
[Operation("create_group_file_folder")]
|
||||
public class CreateGroupFileFolderOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotCreateFolder>(SerializerOptions.DefaultOptions) is { } folder)
|
||||
{
|
||||
var res = await context.GroupFSCreateFolder(folder.GroupId, folder.Name);
|
||||
return new OneBotResult(new JsonObject { { "msg", res.Item2 } }, res.Item1, res.Item1 == 0 ? "ok" : "failed");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
|
||||
[Operation("delete_group_file_folder")]
|
||||
public class DeleteGroupFileFolderOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotDeleteFolder>(SerializerOptions.DefaultOptions) is { } folder)
|
||||
{
|
||||
var res = await context.GroupFSDeleteFolder(folder.GroupId, folder.FolderId);
|
||||
return new OneBotResult(new JsonObject { { "msg", res.Item2 } }, res.Item1, res.Item1 == 0 ? "ok" : "failed");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
|
||||
[Operation("rename_group_file_folder")]
|
||||
public class RenameGroupFileFolderOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotRenameFolder>(SerializerOptions.DefaultOptions) is { } folder)
|
||||
{
|
||||
var res = await context.GroupFSRenameFolder(folder.GroupId, folder.FolderId, folder.NewFolderName);
|
||||
return new OneBotResult(new JsonObject { { "msg", res.Item2 } }, res.Item1, res.Item1 == 0 ? "ok" : "failed");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.File;
|
||||
|
||||
[Operation("get_private_file_url")]
|
||||
public class GetPrivateFileUrlOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotGetPrivateFile>(SerializerOptions.DefaultOptions) is { } url)
|
||||
{
|
||||
string raw = await context.FetchPrivateFSDownload(url.FileId, url.FileHash, url.UserId);
|
||||
return new OneBotResult(new JsonObject { { "url", raw } }, 0, "ok");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.Core.Message.Entity;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.File;
|
||||
|
||||
[Operation("upload_group_file")]
|
||||
public class UploadGroupFileOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotUploadGroupFile>(SerializerOptions.DefaultOptions) is { } file)
|
||||
{
|
||||
var entity = new FileEntity(file.File);
|
||||
if (file.Name != null) entity.FileName = file.Name;
|
||||
|
||||
bool result = await context.GroupFSUpload(file.GroupId, entity, file.Folder ?? "/");
|
||||
return new OneBotResult(null, result ? 0 : 1, result ? "ok" : "failed");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.Core.Message.Entity;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.File;
|
||||
|
||||
[Operation("upload_private_file")]
|
||||
public class UploadPrivateFile : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotUploadPrivateFile>(SerializerOptions.DefaultOptions) is { } file)
|
||||
{
|
||||
var entity = new FileEntity(file.File);
|
||||
if (file.Name != null) entity.FileName = file.Name;
|
||||
|
||||
bool result = await context.UploadFriendFile(file.UserId, entity);
|
||||
return new OneBotResult(null, result ? 0 : 1, result ? "ok" : "failed");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Generic;
|
||||
|
||||
[Operation("delete_friend")]
|
||||
public class DeleteFriendOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotDeleteFriend>(SerializerOptions.DefaultOptions) is {} delete)
|
||||
{
|
||||
return await context.DeleteFriend(delete.UserId, delete.Block)
|
||||
? new OneBotResult(null, 0, "ok")
|
||||
: new OneBotResult(null, 0, "failed");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Generic;
|
||||
|
||||
[Operation("fetch_custom_face")]
|
||||
internal class FetchCustomFaceOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload) =>
|
||||
new(await context.FetchCustomFace(), 0, "ok");
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Generic;
|
||||
|
||||
[Operation("fetch_mface_key")]
|
||||
internal class FetchMFaceKeyOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload?["emoji_ids"]?.Deserialize<string[]>() is { Length: not 0 } emojiIds)
|
||||
{
|
||||
if (await context.FetchMarketFaceKey([.. emojiIds]) is { Count: not 0 } keys)
|
||||
{
|
||||
return new(keys, 0, "ok");
|
||||
}
|
||||
else return new(Array.Empty<string>(), -1, "failed");
|
||||
}
|
||||
else throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Message;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
using Lagrange.OneBot.Database;
|
||||
using LiteDB;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Generic;
|
||||
|
||||
|
||||
[Operation(".join_friend_emoji_chain")]
|
||||
public class FriendJoinEmojiChainOperation(LiteDatabase database) : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotPrivateJoinEmojiChain>(SerializerOptions.DefaultOptions) is { } data)
|
||||
{
|
||||
var message = (MessageChain)database.GetCollection<MessageRecord>().FindById(data.MessageId);
|
||||
bool res = await context.FriendJoinEmojiChain(data.UserId, data.EmojiId, message.Sequence);
|
||||
return new OneBotResult(null, res ? 0 : -1, res ? "ok" : "failed");
|
||||
}
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Generic;
|
||||
|
||||
[Operation("get_ai_characters")]
|
||||
public class GetAiCharacters : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
var message = payload.Deserialize<OneBotGetAiCharacters>(SerializerOptions.DefaultOptions)
|
||||
?? throw new Exception();
|
||||
|
||||
var (code, errMsg, result) = await context.GetAiCharacters(message.ChatType, message.GroupId);
|
||||
if (code != 0) return new(null, -1, "failed");
|
||||
|
||||
return result != null
|
||||
? new OneBotResult(result.Select(x => new OneBotAiCharacters(x)), 0, "ok")
|
||||
: new OneBotResult(null, -1, "failed");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Generic;
|
||||
|
||||
[Operation("get_cookies")]
|
||||
public class GetCookiesOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload?["domain"]?.ToString() is { } domain)
|
||||
{
|
||||
var cookies = await context.FetchCookies([domain]);
|
||||
return new OneBotResult(new JsonObject { { "cookies", cookies[0] } }, 0, "ok");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Notify;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Generic;
|
||||
|
||||
[Operation("get_credentials")]
|
||||
public class GetCredentialsOperation(TicketService ticket) : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload?["domain"]?.ToString() is { } domain)
|
||||
{
|
||||
var cookies = await context.FetchCookies([domain]);
|
||||
int bkn = await ticket.GetCsrfToken();
|
||||
|
||||
return new OneBotResult(new JsonObject
|
||||
{
|
||||
{ "cookies", cookies[0] },
|
||||
{ "csrf_token", bkn }
|
||||
}, 0, "ok");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Notify;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Generic;
|
||||
|
||||
[Operation("get_csrf_token")]
|
||||
public class GetCsrfTokenOperation(TicketService ticket) : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
int bkn = await ticket.GetCsrfToken();
|
||||
return new OneBotResult(new JsonObject { { "token", bkn } }, 0, "ok");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Internal.Event.System;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Entity.Action.Response;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Generic;
|
||||
|
||||
[Operation("get_rkey")]
|
||||
public class GetRkey : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
var fetchRKeyEvent = FetchRKeyEvent.Create();
|
||||
var events = await context.ContextCollection.Business.SendEvent(fetchRKeyEvent);
|
||||
var rKeyEvent = (FetchRKeyEvent)events[0];
|
||||
if (rKeyEvent.ResultCode != 0) return new OneBotResult(null, rKeyEvent.ResultCode, "failed");
|
||||
var response = new OneBotGetRkeyResponse(rKeyEvent.RKeys.Select(x => new OneBotRkey
|
||||
{
|
||||
Type = x.Type == 10
|
||||
? "private"
|
||||
: "group",
|
||||
Rkey = x.Rkey,
|
||||
CreateTime = x.RkeyCreateTime,
|
||||
TtlSeconds = x.RkeyTtlSec
|
||||
})
|
||||
.ToList());
|
||||
return new OneBotResult(response, 0, "ok");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Message;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
using Lagrange.OneBot.Database;
|
||||
using LiteDB;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Generic;
|
||||
|
||||
|
||||
[Operation(".join_group_emoji_chain")]
|
||||
public class GroupJoinEmojiChainOperation(LiteDatabase database) : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotGroupJoinEmojiChain>(SerializerOptions.DefaultOptions) is { } data)
|
||||
{
|
||||
var message = (MessageChain)database.GetCollection<MessageRecord>().FindById(data.MessageId);
|
||||
bool res = await context.GroupJoinEmojiChain(data.GroupId, data.EmojiId, message.Sequence);
|
||||
return new OneBotResult(null, res ? 0 : -1, res ? "ok" : "failed");
|
||||
}
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Message.Entity;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
using Lagrange.OneBot.Message.Entity;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Generic;
|
||||
|
||||
|
||||
[Operation(".ocr_image")]
|
||||
[Operation("ocr_image")]
|
||||
public class OcrImageOperation() : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotOcrImage>(SerializerOptions.DefaultOptions) is { } data && CommonResolver.ResolveStream(data.Image) is { } stream)
|
||||
{
|
||||
var entity = new ImageEntity(stream);
|
||||
var res = await context.OcrImage(entity);
|
||||
return new OneBotResult(res, 0, "ok");
|
||||
}
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Generic;
|
||||
|
||||
[Operation("send_like")]
|
||||
public class SendLikeOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotSendLike>(SerializerOptions.DefaultOptions) is { } like)
|
||||
{
|
||||
return await context.Like(like.UserId, like.Times ?? 1) // the times is ignored to simulate the real user behaviour
|
||||
? new OneBotResult(null, 0, "ok")
|
||||
: new OneBotResult(null, 0, "user not found in the buffer");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Internal.Packets;
|
||||
using Lagrange.Core.Utility.Extension;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Entity.Action.Response;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Generic;
|
||||
|
||||
[Operation(".send_packet")]
|
||||
public class SendPacketOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotSendPacket>() is { } send)
|
||||
{
|
||||
int sequence = context.ContextCollection.Service.GetNewSequence();
|
||||
var ssoPacket = new SsoPacket(send.Type, send.Command, (uint)sequence, send.Data.UnHex());
|
||||
var task = await context.ContextCollection.Packet.SendPacket(ssoPacket);
|
||||
|
||||
return new OneBotResult(new OneBotSendPacketResponse
|
||||
{
|
||||
Sequence = sequence,
|
||||
RetCode = task.RetCode,
|
||||
Extra = task.Extra,
|
||||
Result = task.Payload.Hex()
|
||||
}, 0, "ok");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.Core.Message.Entity;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Message.Entity;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Generic;
|
||||
|
||||
[Operation("set_qq_avatar")]
|
||||
public class SetQQAvatar : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload?["file"]?.ToString() is { } portrait)
|
||||
{
|
||||
var image = CommonResolver.ResolveStream(portrait);
|
||||
if (image == null) throw new Exception();
|
||||
|
||||
var imageEntity = new ImageEntity(image);
|
||||
bool result = await context.SetAvatar(imageEntity);
|
||||
return new OneBotResult(null, result ? 0 : 1, "");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Generic;
|
||||
|
||||
[Operation("set_restart")]
|
||||
public class SetRestartOperation(IHost host) : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new OneBotResult(null, 0, "ok");
|
||||
}
|
||||
finally
|
||||
{
|
||||
await host.StopAsync();
|
||||
await host.StartAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Notify;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Group;
|
||||
|
||||
[Operation("_del_group_notice")]
|
||||
public class DeleteGroupMemoOperation(TicketService ticket) : IOperation
|
||||
{
|
||||
private const string Url = "https://web.qun.qq.com/cgi-bin/announce/del_feed";
|
||||
private const string Domain = "qun.qq.com";
|
||||
|
||||
private async Task<bool> DeleteGroupNotice(OneBotDeleteGroupMemo memo)
|
||||
{
|
||||
string url = $"{Url}?fid={memo.NoticeId}&qid={memo.GroupId}&bkn={await ticket.GetCsrfToken()}&ft=23&op=1";
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, url);
|
||||
try
|
||||
{
|
||||
var response = await ticket.SendAsync(request, Domain);
|
||||
response.EnsureSuccessStatusCode();
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotDeleteGroupMemo>(SerializerOptions.DefaultOptions) is { } memo)
|
||||
{
|
||||
return await DeleteGroupNotice(memo)
|
||||
? new OneBotResult(null, 0, "ok")
|
||||
: new OneBotResult(null, -1, "failed");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Group;
|
||||
|
||||
[Operation("get_ai_record")]
|
||||
public class GetAiRecordOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
var message = payload.Deserialize<OneBotGetAiRecord>(SerializerOptions.DefaultOptions);
|
||||
if (message != null)
|
||||
{
|
||||
var (code, errMsg, url) = await context.GetGroupGenerateAiRecordUrl(
|
||||
message.GroupId,
|
||||
message.Character,
|
||||
message.Text,
|
||||
message.ChatType
|
||||
);
|
||||
return code != 0 ? new OneBotResult(errMsg, code, "failed") : new OneBotResult(url, 0, "ok");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Text.RegularExpressions;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Notify;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Group;
|
||||
|
||||
[Operation("get_group_honor_info")]
|
||||
public partial class GetGroupHonorInfoOperation(TicketService ticket) : IOperation
|
||||
{
|
||||
[GeneratedRegex(@"window\.__INITIAL_STATE__\s*?=\s*?(\{.*?);")]
|
||||
public static partial Regex HonorRegex();
|
||||
|
||||
private static readonly Dictionary<string, string> Keys = new()
|
||||
{
|
||||
{ "group_id", "group_id" }, { "current_talkative", "currentTalkative" }, { "talkative_list", "talkativeList" },
|
||||
{ "performer_list", "" }, { "legend_list", "legendList" }, { "strong_newbie_list", "strongnewbieList" },
|
||||
{ "emotion_list", "emotionList" }
|
||||
};
|
||||
|
||||
private static readonly Dictionary<string, int> HonorToType = new()
|
||||
{
|
||||
{ "talkative", 1 }, { "performer", 2 }, { "legend", 3 }, { "strong_newbie", 5 }, { "emotion", 6 },
|
||||
};
|
||||
|
||||
private static readonly Dictionary<string, string> KeyToOnebot11 = new()
|
||||
{
|
||||
{"uin", "user_id"}, {"name", "nickname"}, {"nick", "nickname"}, {"desc", "description"}
|
||||
};
|
||||
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotHonorInfo>(SerializerOptions.DefaultOptions) is { } honor)
|
||||
{
|
||||
var result = new JsonObject();
|
||||
var honors = honor.Type == "all"
|
||||
? HonorToType.Select(x => x.Key).ToArray()
|
||||
: [honor.Type];
|
||||
|
||||
result.TryAdd("group_id", honor.GroupId);
|
||||
|
||||
foreach (string honorRaw in honors)
|
||||
{
|
||||
string url = $"https://qun.qq.com/interactive/honorlist?gc={honor.GroupId}&type={HonorToType[honorRaw]}";
|
||||
var response = await ticket.SendAsync(new HttpRequestMessage(HttpMethod.Get, url));
|
||||
string raw = await response.Content.ReadAsStringAsync();
|
||||
var match = HonorRegex().Match(raw);
|
||||
|
||||
if (JsonSerializer.Deserialize<JsonObject>(match.Groups[1].Value) is { } json) // 神经病
|
||||
{
|
||||
foreach (var (key, value) in Keys)
|
||||
{
|
||||
if (json.Remove(value, out var node))
|
||||
{
|
||||
if (node is JsonObject jsonObject)
|
||||
{
|
||||
ProcessJsonObject(jsonObject);
|
||||
}
|
||||
else if (node is JsonArray jsonArray)
|
||||
{
|
||||
foreach (var subNode in jsonArray)
|
||||
{
|
||||
if (subNode is JsonObject subObject)
|
||||
{
|
||||
ProcessJsonObject(subObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (key.Contains(honorRaw)) result.TryAdd(key, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new OneBotResult(result, 0, "ok");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
private static void ProcessJsonObject(JsonObject jsonObject)
|
||||
{
|
||||
foreach (var oldKey in KeyToOnebot11.Keys)
|
||||
{
|
||||
if (jsonObject.Remove(oldKey, out var nodeValue))
|
||||
{
|
||||
jsonObject[KeyToOnebot11[oldKey]] = nodeValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Text.Json.Serialization;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.OneBot.Core.Entity;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Notify;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Group;
|
||||
|
||||
[Operation("_get_group_notice")]
|
||||
public class GetGroupMemoOperation(TicketService ticket) : IOperation
|
||||
{
|
||||
|
||||
private const string Url = "https://web.qun.qq.com/cgi-bin/announce/get_t_list";
|
||||
private const string Domain = "qun.qq.com";
|
||||
|
||||
private async Task<IEnumerable<OneBotGroupNotice>?> GetGroupNotice(OneBotGetGroupMemo memo)
|
||||
{
|
||||
var url = $"{Url}?bkn={await ticket.GetCsrfToken()}&qid={memo.GroupId}&ft=23&ni=1&n=1&i=1&log_read=1&platform=1&s=-1&n=20";
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, url);
|
||||
try
|
||||
{
|
||||
var response = await ticket.SendAsync(request, Domain);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
string content = await response.Content.ReadAsStringAsync();
|
||||
var notices = JsonSerializer.Deserialize<GroupNoticeResponse>(content)!;
|
||||
return notices.Feeds.Concat(notices.Inst)
|
||||
.Select(feed => new OneBotGroupNotice(feed.NoticeId, feed.SenderId, feed.PublishTime,
|
||||
new OneBotGroupNoticeMessage(feed.Message.Text, feed.Message.Images.Select(image => new OneBotGroupNoticeImage(image.Id, image.Height, image.Width)))
|
||||
));
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotGetGroupMemo>(SerializerOptions.DefaultOptions) is { } memo)
|
||||
{
|
||||
var notices = await GetGroupNotice(memo);
|
||||
return notices is null
|
||||
? new OneBotResult(null, -1, "failed")
|
||||
: new OneBotResult(notices, 0, "ok");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
file class GroupNoticeImage
|
||||
{
|
||||
[JsonPropertyName("h")] public string Height { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("w")] public string Width { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("id")] public string Id { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
file class GroupNoticeMessage
|
||||
{
|
||||
[JsonPropertyName("text")] public string Text { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("pics")] public IEnumerable<GroupNoticeImage> Images { get; set; } = [];
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
file class GroupNoticeFeed
|
||||
{
|
||||
[JsonPropertyName("fid")] public string NoticeId { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("u")] public uint SenderId { get; set; }
|
||||
|
||||
[JsonPropertyName("pubt")] public long PublishTime { get; set; }
|
||||
|
||||
[JsonPropertyName("msg")] public GroupNoticeMessage Message { get; set; } = new();
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
file class GroupNoticeResponse
|
||||
{
|
||||
[JsonPropertyName("feeds")] public IEnumerable<GroupNoticeFeed> Feeds { get; set; } = [];
|
||||
|
||||
[JsonPropertyName("inst")] public IEnumerable<GroupNoticeFeed> Inst { get; set; } = [];
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Group;
|
||||
|
||||
[Operation("set_group_admin")]
|
||||
public class SetGroupAdminOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
var message = payload.Deserialize<OneBotSetGroupAdmin>(SerializerOptions.DefaultOptions);
|
||||
|
||||
if (message != null)
|
||||
{
|
||||
bool _ = await context.SetGroupAdmin(message.GroupId, message.UserId, message.Enable);
|
||||
return new OneBotResult(null, 0, "ok");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Group;
|
||||
|
||||
[Operation("set_group_ban")]
|
||||
public class SetGroupBanOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
var message = payload.Deserialize<OneBotSetGroupBan>(SerializerOptions.DefaultOptions);
|
||||
|
||||
if (message != null)
|
||||
{
|
||||
bool _ = await context.MuteGroupMember(message.GroupId, message.UserId, message.Duration);
|
||||
return new OneBotResult(null, 0, "ok");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Group;
|
||||
|
||||
[Operation("set_group_bot_status")]
|
||||
public class SetGroupBotOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
var message = payload.Deserialize<OneBotSetGroupBot>(SerializerOptions.DefaultOptions);
|
||||
|
||||
if (message != null)
|
||||
{
|
||||
bool _ = await context.SetGroupBot(message.BotId, message.Enable , message.GroupId);
|
||||
|
||||
return new OneBotResult(message.BotId, 0, "ok");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Group;
|
||||
|
||||
[Operation("send_group_bot_callback")]
|
||||
public class SetGroupBothdOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
var message = payload.Deserialize<OneBotSetGroupBothd>(SerializerOptions.DefaultOptions);
|
||||
|
||||
if (message != null)
|
||||
{
|
||||
bool _ = await context.SetGroupBotHD(message.BotId, message.GroupId, message.Data_1, message.Data_2);
|
||||
|
||||
return new OneBotResult(message.BotId, 0, "ok");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Group;
|
||||
|
||||
[Operation("set_group_card")]
|
||||
public class SetGroupCardOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
var message = payload.Deserialize<OneBotSetGroupCard>(SerializerOptions.DefaultOptions);
|
||||
|
||||
if (message != null)
|
||||
{
|
||||
bool _ = await context.RenameGroupMember(message.GroupId, message.UserId, message.Card);
|
||||
return new OneBotResult(null, 0, "ok");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Group;
|
||||
|
||||
[Operation("set_group_kick")]
|
||||
public class SetGroupKickOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
var message = payload.Deserialize<OneBotSetGroupKick>(SerializerOptions.DefaultOptions);
|
||||
|
||||
if (message != null)
|
||||
{
|
||||
bool _ = await context.KickGroupMember(message.GroupId, message.UserId, message.RejectAddRequest);
|
||||
return new OneBotResult(null, 0, "ok");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Group;
|
||||
|
||||
[Operation("set_group_leave")]
|
||||
public class SetGroupLeaveOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
var message = payload.Deserialize<OneBotSetGroupLeave>(SerializerOptions.DefaultOptions);
|
||||
|
||||
if (message != null)
|
||||
{
|
||||
bool _ = await context.LeaveGroup(message.GroupId); // TODO: Figure out is_dismiss
|
||||
return new OneBotResult(null, 0, "ok");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Text.Json.Serialization;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Notify;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Group;
|
||||
|
||||
[Operation("_send_group_notice")]
|
||||
public class SetGroupMemoOperation(TicketService ticket) : IOperation
|
||||
{
|
||||
private const string Url = "https://web.qun.qq.com/cgi-bin/announce/add_qun_notice?bkn=";
|
||||
private const string UserAgent = "Dalvik/2.1.0 (Linux; U; Android 7.1.2; PCRT00 Build/N2G48H)";
|
||||
private const string Domain = "qun.qq.com";
|
||||
|
||||
private async Task<string?> SendGroupNoticeSimple(OneBotSetGroupMemo memo)
|
||||
{
|
||||
int bkn = await ticket.GetCsrfToken();
|
||||
string body = $"qid={memo.GroupId}&bkn={bkn}&text={Uri.EscapeDataString(memo.Content)}&pinned=0&type=1&settings={{\"is_show_edit_card\":0,\"tip_window_type\":1,\"confirm_required\":1}}";
|
||||
string url = Url + bkn;
|
||||
try
|
||||
{
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, url);
|
||||
request.Headers.UserAgent.ParseAdd(UserAgent);
|
||||
request.Content = new StringContent(body, Encoding.UTF8, "application/json");
|
||||
var response = await ticket.SendAsync(request, Domain);
|
||||
response.EnsureSuccessStatusCode();
|
||||
string content = await response.Content.ReadAsStringAsync();
|
||||
|
||||
var sendResponse = JsonSerializer.Deserialize<NoticeSendResponse>(content);
|
||||
return sendResponse?.NoticeId;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotSetGroupMemo>(SerializerOptions.DefaultOptions) is { } memo)
|
||||
{
|
||||
var noticeId = string.IsNullOrEmpty(memo.Image)
|
||||
? await SendGroupNoticeSimple(memo)
|
||||
: throw new NotImplementedException();
|
||||
|
||||
return noticeId is null
|
||||
? new OneBotResult(null, -1, "failed")
|
||||
: new OneBotResult(noticeId, 0, "ok");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
file class NoticeSendResponse
|
||||
{
|
||||
[JsonPropertyName("new_fid")] public string NoticeId { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
file class NoticeImageUploadResponse
|
||||
{
|
||||
[JsonPropertyName("ec")] public int ErrorCode { get; set; }
|
||||
[JsonPropertyName("em")] public string ErrorMessage { get; set; } = string.Empty;
|
||||
[JsonPropertyName("id")] public string Id { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
file class GroupNoticeImage
|
||||
{
|
||||
[JsonPropertyName("h")] public string Height { get; set; } = string.Empty;
|
||||
[JsonPropertyName("w")] public string Width { get; set; } = string.Empty;
|
||||
[JsonPropertyName("id")] public string Id { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Group;
|
||||
|
||||
[Operation("set_group_name")]
|
||||
public class SetGroupNameOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
var message = payload.Deserialize<OneBotSetGroupName>(SerializerOptions.DefaultOptions);
|
||||
|
||||
if (message != null)
|
||||
{
|
||||
bool _ = await context.RenameGroup(message.GroupId, message.GroupName);
|
||||
return new OneBotResult(null, 0, "ok");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.Core.Message.Entity;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
using Lagrange.OneBot.Message.Entity;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Group;
|
||||
|
||||
[Operation("set_group_portrait")]
|
||||
public class SetGroupPortraitOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotSetGroupPortrait>(SerializerOptions.DefaultOptions) is { } portrait)
|
||||
{
|
||||
var image = CommonResolver.ResolveStream(portrait.File);
|
||||
if (image == null) throw new Exception();
|
||||
|
||||
var imageEntity = new ImageEntity(image);
|
||||
bool result = await context.GroupSetAvatar(portrait.GroupId, imageEntity);
|
||||
return new OneBotResult(null, result ? 0 : 1, "");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.Core.Message;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
using Lagrange.OneBot.Database;
|
||||
using LiteDB;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Group;
|
||||
|
||||
[Operation("set_group_reaction")]
|
||||
public class SetGroupReactionOperation(LiteDatabase database) : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotSetGroupReaction>(SerializerOptions.DefaultOptions) is { } data)
|
||||
{
|
||||
var message = (MessageChain)database.GetCollection<MessageRecord>().FindById(data.MessageId);
|
||||
|
||||
bool result = await context.GroupSetMessageReaction(data.GroupId, message.Sequence, data.Code, data.IsAdd);
|
||||
return new OneBotResult(null, result ? 0 : 1, result ? "ok" : "failed");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Group;
|
||||
|
||||
[Operation("set_group_special_title")]
|
||||
public class SetGroupSpecialTitleOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotSetGroupSpecialTitle>(SerializerOptions.DefaultOptions) is { } title)
|
||||
{
|
||||
bool result = await context.GroupSetSpecialTitle(title.GroupId, title.UserId, title.SpecialTitle);
|
||||
return new OneBotResult(null, result ? 0 : 1, result ? "ok" : "failed");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Group;
|
||||
|
||||
[Operation("set_group_whole_ban")]
|
||||
public class SetGroupWholeBanOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
var message = payload.Deserialize<OneBotSetGroupWholeBan>(SerializerOptions.DefaultOptions);
|
||||
|
||||
if (message != null)
|
||||
{
|
||||
bool _ = await context.MuteGroupGlobal(message.GroupId, message.Enable);
|
||||
return new OneBotResult(null, 0, "ok");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
10
Lagrange.Core/Lagrange.OneBot/Core/Operation/IOperation.cs
Normal file
10
Lagrange.Core/Lagrange.OneBot/Core/Operation/IOperation.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation;
|
||||
|
||||
public interface IOperation
|
||||
{
|
||||
public Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Info;
|
||||
|
||||
[Operation("get_friend_list")]
|
||||
public class GetFriendListOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload) =>
|
||||
new((await context.FetchFriends(true)).Select(friend => new OneBotFriend
|
||||
{
|
||||
UserId = friend.Uin,
|
||||
QId = friend.Qid,
|
||||
NickName = friend.Nickname,
|
||||
Remark = friend.Remarks,
|
||||
Group = new(friend.Group.GroupId, friend.Group.GroupName)
|
||||
}).ToArray(), 0, "ok");
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Info;
|
||||
|
||||
[Operation("get_group_info")]
|
||||
public class GetGroupInfoOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotGetGroupInfo>(SerializerOptions.DefaultOptions) is { } message)
|
||||
{
|
||||
var result = (await context.FetchGroups(message.NoCache)).FirstOrDefault(x => x.GroupUin == message.GroupId);
|
||||
|
||||
if (result == null && !message.NoCache)
|
||||
{
|
||||
result = (await context.FetchGroups(true)).FirstOrDefault(x => x.GroupUin == message.GroupId);
|
||||
}
|
||||
|
||||
return result == null
|
||||
? new OneBotResult(null, -1, "failed")
|
||||
: new OneBotResult(new OneBotGroup(result), 0, "ok");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Info;
|
||||
|
||||
[Operation("get_group_list")]
|
||||
public class GetGroupListOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotGetGroupInfo>(SerializerOptions.DefaultOptions) is { } message)
|
||||
{
|
||||
var result = await context.FetchGroups(message.NoCache);
|
||||
return new OneBotResult(result.Select(x => new OneBotGroup(x)), 0, "ok");
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await context.FetchGroups();
|
||||
return new OneBotResult(result.Select(x => new OneBotGroup(x)), 0, "ok");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Info;
|
||||
|
||||
[Operation("get_group_member_info")]
|
||||
public class GetGroupMemberInfoOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotGetGroupMemberInfo>(SerializerOptions.DefaultOptions) is { } message)
|
||||
{
|
||||
var result = (await context.FetchMembers(message.GroupId, message.NoCache)).FirstOrDefault(x => x.Uin == message.UserId);
|
||||
|
||||
return result == null
|
||||
? new OneBotResult(null, -1, "failed")
|
||||
: new OneBotResult(new OneBotGroupMember(message.GroupId,
|
||||
result.Uin,
|
||||
result.Permission.ToString().ToLower(),
|
||||
result.GroupLevel.ToString(), result.MemberCard, result.MemberName, result.SpecialTitle,
|
||||
(uint)new DateTimeOffset(result.JoinTime).ToUnixTimeSeconds(),
|
||||
(uint)new DateTimeOffset(result.LastMsgTime).ToUnixTimeSeconds()),
|
||||
0, "ok");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Info;
|
||||
|
||||
[Operation("get_group_member_list")]
|
||||
public class GetGroupMemberListOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotGetGroupMemberInfo>(SerializerOptions.DefaultOptions) is { } message)
|
||||
{
|
||||
var result = await context.FetchMembers(message.GroupId, message.NoCache);
|
||||
return new OneBotResult(result.Select(x => new OneBotGroupMember(message.GroupId, x.Uin, x.Permission.ToString().ToLower(), x.GroupLevel.ToString(), x.MemberCard, x.MemberName, x.SpecialTitle, (uint)new DateTimeOffset(x.JoinTime).ToUnixTimeSeconds(), (uint)new DateTimeOffset(x.LastMsgTime).ToUnixTimeSeconds())), 0, "ok");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Entity.Action.Response;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Info;
|
||||
|
||||
[Operation("get_login_info")]
|
||||
public class GetLoginInfoOperation : IOperation
|
||||
{
|
||||
public Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
var keystore = context.ContextCollection.Keystore;
|
||||
var result = new OneBotLoginInfoResponse(keystore.Uin, keystore.Info?.Name ?? "");
|
||||
return Task.FromResult(new OneBotResult(result, 0, "ok"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Entity.Action.Response;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Info;
|
||||
|
||||
[Operation("get_status")]
|
||||
public class GetStatusOperation : IOperation
|
||||
{
|
||||
public Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
return Task.FromResult(new OneBotResult(new OneBotGetStatusResponse
|
||||
{
|
||||
Memory = GC.GetTotalMemory(false)
|
||||
}, 0, "ok"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Entity;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
using Lagrange.OneBot.Utility;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Info;
|
||||
|
||||
[Operation("get_stranger_info")]
|
||||
public class GetStrangerInfoOperation : IOperation
|
||||
{
|
||||
private static readonly Dictionary<uint, string> _statusMessage = new()
|
||||
{
|
||||
{ 1, "在线" },
|
||||
{ 3, "离开" },
|
||||
{ 4, "隐身/离线" },
|
||||
{ 5, "忙碌" },
|
||||
{ 6, "Q我吧" },
|
||||
{ 7, "请勿打扰" },
|
||||
{ 263169, "听歌中" },
|
||||
{ 15205121, "我的电量" },
|
||||
{ 16713473, "做好事" },
|
||||
{ 13829889, "出去浪" },
|
||||
{ 14616321, "去旅行" },
|
||||
{ 14550785, "被掏空" },
|
||||
{ 14747393, "今日步数" },
|
||||
{ 394241, "今日天气" },
|
||||
{ 14878465, "我crush了" },
|
||||
{ 14026497, "爱你" },
|
||||
{ 1770497, "恋爱中" },
|
||||
{ 3081217, "好运锦鲤" },
|
||||
{ 11600897, "水逆退散" },
|
||||
{ 2098177, "嗨到飞起" },
|
||||
{ 2229249, "元气满满" },
|
||||
{ 2556929, "一言难尽" },
|
||||
{ 13698817, "难得糊涂" },
|
||||
{ 7931137, "emo中" },
|
||||
{ 2491393, "我太难了" },
|
||||
{ 14485249, "我想开了" },
|
||||
{ 1836033, "我没事" },
|
||||
{ 2425857, "想静静" },
|
||||
{ 2294785, "悠哉哉" },
|
||||
{ 15926017, "信号弱" },
|
||||
{ 16253697, "睡觉中" },
|
||||
{ 14419713, "肝作业" },
|
||||
{ 16384769, "学习中" },
|
||||
{ 15140609, "搬砖中" },
|
||||
{ 1312001, "摸鱼中" },
|
||||
{ 2360321, "无聊中" },
|
||||
{ 197633, "timi中" },
|
||||
{ 15271681, "一起元梦" },
|
||||
{ 15337217, "求星搭子" },
|
||||
{ 525313, "熬夜中" },
|
||||
{ 16581377, "追剧中" },
|
||||
{ 13633281, "自定义状态"}
|
||||
};
|
||||
|
||||
private static readonly Dictionary<uint, string> _BusinessName = new()
|
||||
{
|
||||
{ 113, "QQ大会员" },
|
||||
{ 1, "QQ会员" },
|
||||
{ 102, "黄钻" },
|
||||
{ 117, "QQ集卡" },
|
||||
{ 119, "情侣会员" },
|
||||
{ 103, "绿钻" },
|
||||
{ 4, "腾讯视频" },
|
||||
{ 108, "大王超级会员" },
|
||||
{ 104, "情侣个性钻" },
|
||||
{ 105, "微云会员"},
|
||||
{ 101, "红钻"},
|
||||
{ 115, "cf游戏特权"},
|
||||
{ 118, "蓝钻"},
|
||||
{ 107, "SVIP+腾讯视频"}
|
||||
};
|
||||
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotGetStrangerInfo>(SerializerOptions.DefaultOptions) is { } stranger)
|
||||
{
|
||||
if (await context.FetchUserInfo(stranger.UserId, stranger.NoCache) is { } info)
|
||||
{
|
||||
return new OneBotResult(new OneBotStranger
|
||||
{
|
||||
UserId = info.Uin,
|
||||
Avatar = info.Avatar,
|
||||
QId = info.Qid,
|
||||
NickName = info.Nickname,
|
||||
Sex = info.Gender.ToOneBotString(),
|
||||
Age = info.Age,
|
||||
Level = info.Level,
|
||||
Sign = info.Sign ?? string.Empty,
|
||||
Status = new()
|
||||
{
|
||||
StatusId = info.Status.StatusId,
|
||||
FaceId = info.Status.FaceId,
|
||||
Message = info.Status.StatusId != 13633281
|
||||
? _statusMessage.GetValueOrDefault(info.Status.StatusId)
|
||||
: info.Status.Msg
|
||||
},
|
||||
RegisterTime = info.RegisterTime,
|
||||
Business = BusinessList(info.Business)
|
||||
}, 0, "ok");
|
||||
}
|
||||
|
||||
return new OneBotResult(null, -1, "failed");
|
||||
}
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
private List<OneBotBusiness> BusinessList(List<BusinessCustom> businessCustomList)
|
||||
{
|
||||
return businessCustomList.Select(b => new OneBotBusiness
|
||||
{
|
||||
Type = b.Type,
|
||||
Name = (b.IsPro == 1 ? "超级" : "") + (_BusinessName.GetValueOrDefault(b.Type) ?? "未知"),
|
||||
Level = b.Level,
|
||||
Icon = b.Icon,
|
||||
IsPro = b.IsPro,
|
||||
IsYear = b.IsYear
|
||||
}).ToList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Entity.Action.Response;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Info;
|
||||
|
||||
[Operation("get_version_info")]
|
||||
public class GetVersionInfoOperation : IOperation
|
||||
{
|
||||
public Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
var appInfo = context.ContextCollection.AppInfo;
|
||||
string version = $"{appInfo.Os} | {appInfo.CurrentVersion}";
|
||||
|
||||
return Task.FromResult(new OneBotResult(new OneBotVersionInfoResponse(version), 0, "ok"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.Core.Message;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
using Lagrange.OneBot.Database;
|
||||
using LiteDB;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Message;
|
||||
|
||||
[Operation("delete_essence_msg")]
|
||||
public class DeleteEssenceMessageOperation(LiteDatabase database) : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotGetMessage>(SerializerOptions.DefaultOptions) is { } getMsg)
|
||||
{
|
||||
var record = database.GetCollection<MessageRecord>().FindById(getMsg.MessageId);
|
||||
var chain = (MessageChain)record;
|
||||
bool result = await context.RemoveEssenceMessage(chain);
|
||||
return new OneBotResult(null, result ? 0 : 1, result ? "ok" : "failed");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.Core.Message;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
using Lagrange.OneBot.Database;
|
||||
using LiteDB;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Message;
|
||||
|
||||
[Operation("delete_msg")]
|
||||
public class DeleteMessageOperation(LiteDatabase database) : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotGetMessage>(SerializerOptions.DefaultOptions) is { } getMsg)
|
||||
{
|
||||
var record = database.GetCollection<MessageRecord>().FindById(getMsg.MessageId);
|
||||
var chain = (MessageChain)record;
|
||||
|
||||
if (chain.IsGroup && await context.RecallGroupMessage(chain)) return new OneBotResult(null, 0, "ok");
|
||||
if (!chain.IsGroup && await context.RecallFriendMessage(chain)) return new OneBotResult(null, 0, "ok");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Message;
|
||||
|
||||
[Operation("friend_poke")]
|
||||
public class FriendPokeOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotFriendPoke>(SerializerOptions.DefaultOptions) is { } poke)
|
||||
{
|
||||
bool result = await context.FriendPoke(poke.UserId);
|
||||
return new OneBotResult(null, result ? 0 : 1, result ? "ok" : "failed");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Text.Json.Serialization;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Entity.Message;
|
||||
using Lagrange.OneBot.Core.Notify;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
using Lagrange.OneBot.Database;
|
||||
using Lagrange.OneBot.Message.Entity;
|
||||
|
||||
#pragma warning disable CS8618
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Message;
|
||||
|
||||
[Operation("get_essence_msg_list")]
|
||||
public class GetEssenceMessageListOperation(TicketService ticket) : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotEssenceMessage>(SerializerOptions.DefaultOptions) is { } essenceMsg)
|
||||
{
|
||||
int bkn = await ticket.GetCsrfToken();
|
||||
int page = 0;
|
||||
var essence = new List<OneBotEssenceMessageSegment>();
|
||||
|
||||
while (true)
|
||||
{
|
||||
string url = $"https://qun.qq.com/cgi-bin/group_digest/digest_list?random=7800&X-CROSS-ORIGIN=fetch&group_code={essenceMsg.GroupId}&page_start={page}&page_limit=20&bkn={bkn}";
|
||||
var response = await ticket.SendAsync(new HttpRequestMessage(HttpMethod.Get, url));
|
||||
string raw = await response.Content.ReadAsStringAsync();
|
||||
var @object = JsonSerializer.Deserialize<RequestBody>(raw);
|
||||
if (@object?.Data.MsgList == null) break;
|
||||
|
||||
foreach (var msg in @object.Data.MsgList)
|
||||
{
|
||||
essence.Add(new OneBotEssenceMessageSegment
|
||||
{
|
||||
SenderId = uint.Parse(msg.SenderUin),
|
||||
SenderNick = msg.SenderNick,
|
||||
SenderTime = msg.SenderTime,
|
||||
OperatorId = uint.Parse(msg.AddDigestUin),
|
||||
OperatorNick = msg.AddDigestNick,
|
||||
OperatorTime = msg.AddDigestTime,
|
||||
MessageId = MessageRecord.CalcMessageHash(msg.MsgRandom, msg.MsgSeq),
|
||||
Content = ConvertToSegment(msg.MsgContent)
|
||||
});
|
||||
}
|
||||
|
||||
if (@object.Data.IsEnd) break;
|
||||
|
||||
page++;
|
||||
}
|
||||
|
||||
return new OneBotResult(essence, 0, "ok");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
private static List<OneBotSegment> ConvertToSegment(IEnumerable<JsonObject> elements)
|
||||
{
|
||||
var segments = new List<OneBotSegment>();
|
||||
foreach (var msg in elements)
|
||||
{
|
||||
uint type = msg["msg_type"]?.GetValue<uint>() ?? throw new InvalidDataException("Invalid type");
|
||||
var segment = type switch
|
||||
{
|
||||
1 => new OneBotSegment("text", new TextSegment(msg["text"]?.GetValue<string>() ?? "")),
|
||||
2 => new OneBotSegment("face", new FaceSegment(msg["face_index"]?.GetValue<int?>() ?? 0)),
|
||||
3 => new OneBotSegment("image", new ImageSegment(msg["image_url"]?.GetValue<string>() ?? "", "")),
|
||||
4 => new OneBotSegment("video", new VideoSegment(msg["file_thumbnail_url"]?.GetValue<string>() ?? "")),
|
||||
_ => throw new InvalidDataException("Unknown type found in essence msg")
|
||||
};
|
||||
segments.Add(segment);
|
||||
}
|
||||
|
||||
return segments;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
file class RequestBody
|
||||
{
|
||||
[JsonPropertyName("retcode")] public long Retcode { get; set; }
|
||||
|
||||
[JsonPropertyName("retmsg")] public string Retmsg { get; set; }
|
||||
|
||||
[JsonPropertyName("data")] public Data Data { get; set; }
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
file class Data
|
||||
{
|
||||
[JsonPropertyName("msg_list")] public MsgList[]? MsgList { get; set; }
|
||||
|
||||
[JsonPropertyName("is_end")] public bool IsEnd { get; set; }
|
||||
|
||||
[JsonPropertyName("group_role")] public long GroupRole { get; set; }
|
||||
|
||||
[JsonPropertyName("config_page_url")] public Uri ConfigPageUrl { get; set; }
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
file class MsgList
|
||||
{
|
||||
[JsonPropertyName("group_code")] public string GroupCode { get; set; }
|
||||
|
||||
[JsonPropertyName("msg_seq")] public uint MsgSeq { get; set; }
|
||||
|
||||
[JsonPropertyName("msg_random")] public uint MsgRandom { get; set; }
|
||||
|
||||
[JsonPropertyName("sender_uin")] public string SenderUin { get; set; }
|
||||
|
||||
[JsonPropertyName("sender_nick")] public string SenderNick { get; set; }
|
||||
|
||||
[JsonPropertyName("sender_time")] public uint SenderTime { get; set; }
|
||||
|
||||
[JsonPropertyName("add_digest_uin")] public string AddDigestUin { get; set; }
|
||||
|
||||
[JsonPropertyName("add_digest_nick")] public string AddDigestNick { get; set; }
|
||||
|
||||
[JsonPropertyName("add_digest_time")] public uint AddDigestTime { get; set; }
|
||||
|
||||
[JsonPropertyName("msg_content")] public JsonObject[] MsgContent { get; set; }
|
||||
|
||||
[JsonPropertyName("can_be_removed")] public bool CanBeRemoved { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Entity.Action.Response;
|
||||
using Lagrange.OneBot.Core.Entity.Message;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
using Lagrange.OneBot.Message;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Message;
|
||||
|
||||
[Operation("get_forward_msg")]
|
||||
public class GetForwardMsgOperation(MessageService service) : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotGetForwardMsg>(SerializerOptions.DefaultOptions) is { } forwardMsg)
|
||||
{
|
||||
var (code, chains) = await context.GetMessagesByResId(forwardMsg.Id);
|
||||
|
||||
if (code != 0) return new OneBotResult(null, code, "failed");
|
||||
|
||||
var nodes = new List<OneBotSegment>();
|
||||
if (chains == null) return new OneBotResult(new OneBotGetForwardMsgResponse(nodes), 0, "ok");
|
||||
|
||||
foreach (var chain in chains)
|
||||
{
|
||||
var parsed = service.Convert(chain);
|
||||
var nickname = string.IsNullOrEmpty(chain.FriendInfo?.Nickname)
|
||||
? chain.GroupMemberInfo?.MemberName
|
||||
: chain.FriendInfo?.Nickname;
|
||||
var node = new OneBotNode(chain.FriendUin.ToString(), nickname ?? "", parsed);
|
||||
nodes.Add(new OneBotSegment("node", node));
|
||||
}
|
||||
|
||||
return new OneBotResult(new OneBotGetForwardMsgResponse(nodes), 0, "ok");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.Core.Message;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Entity.Message;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
using Lagrange.OneBot.Database;
|
||||
using Lagrange.OneBot.Message;
|
||||
using LiteDB;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Message;
|
||||
|
||||
[Operation("get_friend_msg_history")]
|
||||
public class GetFriendMessageHistoryOperation(LiteDatabase database, MessageService message) : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotFriendMsgHistory>(SerializerOptions.DefaultOptions) is { } history)
|
||||
{
|
||||
var collection = database.GetCollection<MessageRecord>();
|
||||
var record = history.MessageId == 0
|
||||
? collection.Find(x => x.FriendUin == history.UserId).OrderByDescending(x => x.Time).First()
|
||||
: collection.FindById(history.MessageId);
|
||||
var chain = (MessageChain)record;
|
||||
|
||||
if (await context.GetRoamMessage(chain, history.Count) is { } results)
|
||||
{
|
||||
var messages = results
|
||||
.Select(x => message.ConvertToPrivateMsg(context.BotUin, x))
|
||||
.ToList();
|
||||
return new OneBotResult(new OneBotFriendMsgHistoryResponse(messages), 0, "ok");
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.Core.Message;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Entity.Message;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
using Lagrange.OneBot.Database;
|
||||
using Lagrange.OneBot.Message;
|
||||
using LiteDB;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Message;
|
||||
|
||||
[Operation("get_group_msg_history")]
|
||||
public class GetGroupMessageHistoryOperation(LiteDatabase database, MessageService message) : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotGroupMsgHistory>(SerializerOptions.DefaultOptions) is { } history)
|
||||
{
|
||||
var collection = database.GetCollection<MessageRecord>();
|
||||
var record = history.MessageId == 0
|
||||
? collection.Find(x => x.GroupUin == history.GroupId).OrderByDescending(x => x.Time).First()
|
||||
: collection.FindById(history.MessageId);
|
||||
var chain = (MessageChain)record;
|
||||
|
||||
if (await context.GetGroupMessage(history.GroupId, (uint)(chain.Sequence - history.Count + 1), chain.Sequence) is { } results)
|
||||
{
|
||||
var messages = results
|
||||
.Select(x => message.ConvertToGroupMsg(context.BotUin, x))
|
||||
.ToList();
|
||||
return new OneBotResult(new OneBotGroupMsgHistoryResponse(messages), 0, "ok");
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Entity;
|
||||
using Lagrange.Core.Message;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Entity.Action.Response;
|
||||
using Lagrange.OneBot.Core.Entity.Message;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
using Lagrange.OneBot.Database;
|
||||
using Lagrange.OneBot.Message;
|
||||
using LiteDB;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Message;
|
||||
|
||||
[Operation("get_msg")]
|
||||
public class GetMessageOperation(LiteDatabase database, MessageService service) : IOperation
|
||||
{
|
||||
public Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotGetMessage>(SerializerOptions.DefaultOptions) is { } getMsg)
|
||||
{
|
||||
var record = database.GetCollection<MessageRecord>().FindById(getMsg.MessageId);
|
||||
var chain = (MessageChain)record;
|
||||
|
||||
OneBotSender sender = chain switch
|
||||
{
|
||||
{ GroupMemberInfo: BotGroupMember g } => new(g.Uin, g.MemberName),
|
||||
{ FriendInfo: BotFriend f } => new(f.Uin, f.Nickname),
|
||||
_ => new(chain.FriendUin, "")
|
||||
};
|
||||
|
||||
var elements = service.Convert(chain);
|
||||
var response = new OneBotGetMessageResponse(chain.Time, chain.IsGroup ? "group" : "private", record.MessageHash, sender, elements);
|
||||
|
||||
return Task.FromResult(new OneBotResult(response, 0, "ok"));
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
using System.Net.Http.Json;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Text.Json.Serialization;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Entity.Common;
|
||||
using Lagrange.OneBot.Core.Notify;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Message;
|
||||
|
||||
[Operation("get_music_ark")]
|
||||
public class GetMusicArkOperation(TicketService ticket) : IOperation
|
||||
{
|
||||
private static readonly JsonSerializerOptions _options = new() { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault };
|
||||
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotGetMusicArk>(SerializerOptions.DefaultOptions) is not { } musicArk) throw new Exception();
|
||||
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, "https://docs.qq.com/api/user/qq/login")
|
||||
{
|
||||
Headers =
|
||||
{
|
||||
{ "Accept", "application/json, text/plain, * /*" },
|
||||
{ "referer", "https://docs.qq.com" },
|
||||
}
|
||||
};
|
||||
|
||||
using var response = await ticket.SendAsync(request, "docs.qq.com");
|
||||
var json = await response.Content.ReadFromJsonAsync<JsonObject>();
|
||||
|
||||
string? uid = json?["result"]?["uid"]?.ToString();
|
||||
string? uidKey = json?["result"]?["uid_key"]?.ToString();
|
||||
|
||||
if (string.IsNullOrEmpty(uid) || string.IsNullOrEmpty(uidKey)) throw new Exception();
|
||||
|
||||
var docsArk = new LightApp
|
||||
{
|
||||
App = "com.tencent.tdoc.qqpush",
|
||||
Config = new Config
|
||||
{
|
||||
Ctime = (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
|
||||
Forward = 1,
|
||||
Token = "",
|
||||
Type = "normal",
|
||||
},
|
||||
Extra = new Extra
|
||||
{
|
||||
AppId = 1,
|
||||
AppType = 0,
|
||||
Uin = context.BotUin
|
||||
},
|
||||
Meta = new Meta
|
||||
{
|
||||
Music = new Music
|
||||
{
|
||||
Action = "",
|
||||
AndroidPkgName = "",
|
||||
AppType = 1,
|
||||
AppId = 0,
|
||||
Ctime = (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
|
||||
Desc = musicArk.Desc,
|
||||
JumpUrl = musicArk.JumpUrl, // 在 ntqqpc 可正常使用 手机 噗叽 pia 了
|
||||
MusicUrl = musicArk.MusicUrl, // 在 手机 可正常使用 ntqqpc 噗叽 pia 了
|
||||
Preview = musicArk.Preview, // 需白
|
||||
SourceMsgId = "0",
|
||||
SourceIcon = musicArk.SourceIcon, // 需白
|
||||
SourceUrl = "",
|
||||
Tag = musicArk.Tag,
|
||||
Title = musicArk.Title,
|
||||
Uin = context.BotUin
|
||||
}
|
||||
},
|
||||
Prompt = $"[分享]{musicArk.Title}",
|
||||
Ver = "0.0.0.1",
|
||||
View = "music"
|
||||
};
|
||||
|
||||
var arksRequest = new HttpRequestMessage(HttpMethod.Post, "https://docs.qq.com/v2/push/ark_sig")
|
||||
{
|
||||
Headers =
|
||||
{
|
||||
{ "Cookie", (await ticket.GetCookies("docs.qq.com")) + $"uid={uid}; uid_key={uidKey}" }
|
||||
},
|
||||
Content = JsonContent.Create(new JsonObject {
|
||||
{"ark", JsonSerializer.Serialize(docsArk, _options)},
|
||||
{"object_id", "YjONkUwkdtFr"}
|
||||
})
|
||||
};
|
||||
|
||||
using var arksResponse = await ticket.SendAsync(arksRequest);
|
||||
var arksJson = await arksResponse.Content.ReadFromJsonAsync<JsonObject>();
|
||||
string? arkWithSig = arksJson?["result"]?["ark_with_sig"]?.ToString();
|
||||
|
||||
return arkWithSig != null ? new OneBotResult(arkWithSig, 0, "ok") : new OneBotResult(null, arksJson!["retcode"]!.GetValue<int>(), arksJson!["msg"]!.ToString());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Message;
|
||||
|
||||
[Operation("group_poke")]
|
||||
public class GroupPokeOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotGroupPoke>(SerializerOptions.DefaultOptions) is { } poke)
|
||||
{
|
||||
bool result = await context.GroupPoke(poke.GroupId, poke.UserId);
|
||||
return new OneBotResult(null, result ? 0 : 1, result ? "ok" : "failed");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.Core.Message;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
using Lagrange.OneBot.Database;
|
||||
using LiteDB;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Message;
|
||||
|
||||
[Operation("mark_msg_as_read")]
|
||||
internal class MarkMsgAsReadOperation(LiteDatabase database) : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotGetMessage>(SerializerOptions.DefaultOptions) is { } getMsg)
|
||||
{
|
||||
var record = database.GetCollection<MessageRecord>().FindById(getMsg.MessageId);
|
||||
var chain = (MessageChain)record;
|
||||
bool result = await context.MarkAsRead(chain);
|
||||
return new OneBotResult(null, result ? 0 : 1, result ? "ok" : "failed");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using System.Text.RegularExpressions;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Message;
|
||||
using Lagrange.Core.Utility.Extension;
|
||||
using Lagrange.OneBot.Core.Entity;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Entity.Message;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
using Lagrange.OneBot.Message;
|
||||
using LiteDB;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using JsonSerializer = System.Text.Json.JsonSerializer;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Message;
|
||||
|
||||
public partial class MessageCommon
|
||||
{
|
||||
private readonly ILogger<MessageCommon> _logger;
|
||||
|
||||
private readonly Dictionary<string, SegmentBase> _typeToSegment;
|
||||
|
||||
public MessageCommon(LiteDatabase database, ILogger<MessageCommon> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
_typeToSegment = new Dictionary<string, SegmentBase>();
|
||||
|
||||
foreach (var type in Assembly.GetExecutingAssembly().GetTypes())
|
||||
{
|
||||
if (type.GetCustomAttribute<SegmentSubscriberAttribute>() is { } attribute)
|
||||
{
|
||||
var instance = (SegmentBase)type.CreateInstance(false);
|
||||
instance.Database = database;
|
||||
_typeToSegment[attribute.SendType] = instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public MessageBuilder ParseFakeChain(OneBotFakeNode message)
|
||||
{
|
||||
var builder = MessageBuilder.Friend(uint.Parse(message.Uin)).FriendName(message.Name);
|
||||
BuildMessages(builder, message.Content);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public MessageBuilder ParseFakeChain(OneBotFakeNodeSimple message)
|
||||
{
|
||||
var builder = MessageBuilder.Friend(uint.Parse(message.Uin)).FriendName(message.Name);
|
||||
BuildMessages(builder, message.Content);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public MessageBuilder ParseFakeChain(OneBotFakeNodeText message)
|
||||
{
|
||||
var builder = MessageBuilder.Friend(uint.Parse(message.Uin)).FriendName(message.Name);
|
||||
BuildMessages(builder, message.Content);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public MessageBuilder ParseChain(OneBotMessage message)
|
||||
{
|
||||
var builder = message.MessageType == "private" || message.GroupId == null
|
||||
? MessageBuilder.Friend(message.UserId ?? 0)
|
||||
: MessageBuilder.Group(message.GroupId.Value);
|
||||
BuildMessages(builder, message.Messages);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public MessageBuilder ParseChain(OneBotMessageSimple message)
|
||||
{
|
||||
var builder = message.MessageType == "private" || message.GroupId == null
|
||||
? MessageBuilder.Friend(message.UserId ?? 0)
|
||||
: MessageBuilder.Group(message.GroupId.Value);
|
||||
BuildMessages(builder, message.Messages);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public MessageBuilder ParseChain(OneBotMessageText message)
|
||||
{
|
||||
var builder = message.MessageType == "private" || message.GroupId == null
|
||||
? MessageBuilder.Friend(message.UserId ?? 0)
|
||||
: MessageBuilder.Group(message.GroupId.Value);
|
||||
|
||||
if (message.AutoEscape == true)
|
||||
{
|
||||
builder.Text(message.Messages);
|
||||
}
|
||||
else
|
||||
{
|
||||
BuildMessages(builder, message.Messages);
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public MessageBuilder ParseChain(OneBotPrivateMessage message)
|
||||
{
|
||||
var builder = MessageBuilder.Friend(message.UserId);
|
||||
BuildMessages(builder, message.Messages);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public MessageBuilder ParseChain(OneBotPrivateMessageSimple message)
|
||||
{
|
||||
var builder = MessageBuilder.Friend(message.UserId);
|
||||
BuildMessages(builder, message.Messages);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public MessageBuilder ParseChain(OneBotPrivateMessageText message)
|
||||
{
|
||||
var builder = MessageBuilder.Friend(message.UserId);
|
||||
if (message.AutoEscape == true)
|
||||
{
|
||||
builder.Text(message.Messages);
|
||||
}
|
||||
else
|
||||
{
|
||||
BuildMessages(builder, message.Messages);
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
||||
public MessageBuilder ParseChain(OneBotGroupMessage message)
|
||||
{
|
||||
var builder = MessageBuilder.Group(message.GroupId);
|
||||
BuildMessages(builder, message.Messages);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public MessageBuilder ParseChain(OneBotGroupMessageSimple message)
|
||||
{
|
||||
var builder = MessageBuilder.Group(message.GroupId);
|
||||
BuildMessages(builder, message.Messages);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public MessageBuilder ParseChain(OneBotGroupMessageText message)
|
||||
{
|
||||
var builder = MessageBuilder.Group(message.GroupId);
|
||||
if (message.AutoEscape == true)
|
||||
{
|
||||
builder.Text(message.Messages);
|
||||
}
|
||||
else
|
||||
{
|
||||
BuildMessages(builder, message.Messages);
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
[GeneratedRegex(@"\[CQ:([^,\]]+)(?:,([^,\]]+))*\]")]
|
||||
private static partial Regex CQCodeRegex();
|
||||
|
||||
private static string UnescapeCQ(string str) => str.Replace("[", "[")
|
||||
.Replace("]", "]")
|
||||
.Replace(",", ",")
|
||||
.Replace("&", "&");
|
||||
|
||||
private static string UnescapeText(string str) => str.Replace("[", "[")
|
||||
.Replace("]", "]")
|
||||
.Replace("&", "&");
|
||||
|
||||
private void BuildMessages(MessageBuilder builder, string message)
|
||||
{
|
||||
var matches = CQCodeRegex().Matches(message);
|
||||
int textStart = 0;
|
||||
foreach (var match in matches.Cast<Match>())
|
||||
{
|
||||
if (match.Index > textStart) builder.Text(UnescapeText(message[textStart..match.Index]));
|
||||
textStart = match.Index + match.Length;
|
||||
|
||||
string type = match.Groups[1].Value;
|
||||
if (_typeToSegment.TryGetValue(type, out var instance))
|
||||
{
|
||||
var data = new Dictionary<string, string>();
|
||||
foreach (var capture in match.Groups[2].Captures.Cast<Capture>())
|
||||
{
|
||||
var pair = capture.Value.Split('=', 2);
|
||||
if (pair.Length == 2) data[pair[0]] = UnescapeCQ(pair[1]);
|
||||
}
|
||||
|
||||
if (JsonSerializer.SerializeToElement(data).Deserialize(instance.GetType(), SerializerOptions.DefaultOptions) is SegmentBase cast) instance.Build(builder, cast);
|
||||
else Log.LogCQFailed(_logger, type, string.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
if (textStart < message.Length) builder.Text(UnescapeText(message[textStart..]));
|
||||
}
|
||||
|
||||
private void BuildMessages(MessageBuilder builder, List<OneBotSegment> segments)
|
||||
{
|
||||
foreach (var segment in segments)
|
||||
{
|
||||
if (_typeToSegment.TryGetValue(segment.Type, out var instance))
|
||||
{
|
||||
if (((JsonElement)segment.Data).Deserialize(instance.GetType(), SerializerOptions.DefaultOptions) is SegmentBase cast) instance.Build(builder, cast);
|
||||
else Log.LogCQFailed(_logger, segment.Type, string.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void BuildMessages(MessageBuilder builder, OneBotSegment segment)
|
||||
{
|
||||
if (_typeToSegment.TryGetValue(segment.Type, out var instance))
|
||||
{
|
||||
if (((JsonElement)segment.Data).Deserialize(instance.GetType(), SerializerOptions.DefaultOptions) is SegmentBase cast)
|
||||
{
|
||||
instance.Build(builder, cast);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.LogCQFailed(_logger, segment.Type, string.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<MessageChain> BuildForwardChains(BotContext context, OneBotForward forward)
|
||||
{
|
||||
List<MessageChain> chains = [];
|
||||
|
||||
foreach (var segment in forward.Messages)
|
||||
{
|
||||
if (((JsonElement)segment.Data).Deserialize<OneBotFakeNodeBase>(SerializerOptions.DefaultOptions) is { } element)
|
||||
{
|
||||
var chain = element switch
|
||||
{
|
||||
OneBotFakeNode message => ParseFakeChain(message).Build(),
|
||||
OneBotFakeNodeSimple messageSimple => ParseFakeChain(messageSimple).Build(),
|
||||
OneBotFakeNodeText messageText => ParseFakeChain(messageText).Build(),
|
||||
_ => throw new Exception()
|
||||
};
|
||||
chains.Add(chain); // as fake is constructed, use uid from bot itself to upload image
|
||||
}
|
||||
}
|
||||
|
||||
return chains;
|
||||
}
|
||||
|
||||
private static partial class Log
|
||||
{
|
||||
[LoggerMessage(EventId = 1, Level = LogLevel.Warning, Message = "Segment {type} Deserialization failed for code {code}")]
|
||||
public static partial void LogCQFailed(ILogger logger, string type, string code);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Internal.Event.Message;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Entity.Message;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Message;
|
||||
|
||||
[Operation("send_forward_msg")]
|
||||
public class SendForwardMessageOperation(MessageCommon common) : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotForward>(SerializerOptions.DefaultOptions) is { } forward)
|
||||
{
|
||||
var chains = common.BuildForwardChains(context, forward);
|
||||
|
||||
var @event = MultiMsgUploadEvent.Create(null, chains);
|
||||
var result = await context.ContextCollection.Business.SendEvent(@event);
|
||||
if (result.Count != 0 && result[0] is MultiMsgUploadEvent res)
|
||||
{
|
||||
return new OneBotResult(res.ResId, 0, "ok");
|
||||
}
|
||||
|
||||
return new OneBotResult(null, 404, "failed");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.Core.Message;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Entity.Action.Response;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
using Lagrange.OneBot.Database;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Message;
|
||||
|
||||
[Operation("send_group_ai_record")]
|
||||
public class SendGroupAiRecordOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
var message = payload.Deserialize<OneBotGetAiRecord>(SerializerOptions.DefaultOptions);
|
||||
if (message != null)
|
||||
{
|
||||
(int code, string _, var recordEntity) = await context.GetGroupGenerateAiRecord(
|
||||
message.GroupId,
|
||||
message.Character,
|
||||
message.Text,
|
||||
message.ChatType
|
||||
);
|
||||
return recordEntity != null && code == 0
|
||||
? new OneBotResult(new OneBotMessageResponse(0), code, "ok")
|
||||
: new OneBotResult(null, code, "failed");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.Core.Message;
|
||||
using Lagrange.Core.Message.Entity;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Entity.Action.Response;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
using Lagrange.OneBot.Database;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Message;
|
||||
|
||||
[Operation("send_group_forward_msg")]
|
||||
public class SendGroupForwardOperation(MessageCommon common) : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotGroupForward>(SerializerOptions.DefaultOptions) is { } forward)
|
||||
{
|
||||
var chains = common.BuildForwardChains(context, forward);
|
||||
|
||||
var multi = new MultiMsgEntity(chains);
|
||||
var chain = MessageBuilder.Group(forward.GroupId).Add(multi).Build();
|
||||
var ret = await context.SendMessage(chain);
|
||||
|
||||
if (ret.Result != 0) return new OneBotResult(null, (int)ret.Result, "failed");
|
||||
if (ret.Sequence == null || ret.Sequence == 0) return new OneBotResult(null, 9000, "failed");
|
||||
|
||||
int hash = MessageRecord.CalcMessageHash(chain.MessageId, ret.Sequence ?? 0);
|
||||
|
||||
return new OneBotResult(new OneBotForwardResponse(hash, multi.ResId ?? ""), (int)ret.Result, "ok");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Entity.Action.Response;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
using Lagrange.OneBot.Database;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Message;
|
||||
|
||||
[Operation("send_group_msg")]
|
||||
public sealed class SendGroupMessageOperation(MessageCommon common) : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
var chain = payload.Deserialize<OneBotGroupMessageBase>(SerializerOptions.DefaultOptions) switch
|
||||
{
|
||||
OneBotGroupMessage message => common.ParseChain(message).Build(),
|
||||
OneBotGroupMessageSimple messageSimple => common.ParseChain(messageSimple).Build(),
|
||||
OneBotGroupMessageText messageText => common.ParseChain(messageText).Build(),
|
||||
_ => throw new Exception()
|
||||
};
|
||||
|
||||
var result = await context.SendMessage(chain);
|
||||
|
||||
if (result.Result != 0) return new OneBotResult(null, (int)result.Result, "failed");
|
||||
if (result.Sequence == null || result.Sequence == 0) return new OneBotResult(null, 9000, "failed");
|
||||
|
||||
int hash = MessageRecord.CalcMessageHash(chain.MessageId, result.Sequence ?? 0);
|
||||
|
||||
return new OneBotResult(new OneBotMessageResponse(hash), (int)result.Result, "ok");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Entity.Action.Response;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
using Lagrange.OneBot.Database;
|
||||
using LiteDB;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Message;
|
||||
|
||||
[Operation("send_msg")]
|
||||
public sealed class SendMessageOperation(MessageCommon common, LiteDatabase database) : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
var chain = payload.Deserialize<OneBotMessageBase>(SerializerOptions.DefaultOptions) switch
|
||||
{
|
||||
OneBotMessage message => common.ParseChain(message).Build(),
|
||||
OneBotMessageSimple messageSimple => common.ParseChain(messageSimple).Build(),
|
||||
OneBotMessageText messageText => common.ParseChain(messageText).Build(),
|
||||
_ => throw new Exception()
|
||||
};
|
||||
|
||||
var result = await context.SendMessage(chain);
|
||||
|
||||
if (result.Result != 0) return new OneBotResult(null, (int)result.Result, "failed");
|
||||
if (result.Sequence == null || result.Sequence == 0) return new OneBotResult(null, 9000, "failed");
|
||||
|
||||
int hash = MessageRecord.CalcMessageHash(result.MessageId, result.Sequence ?? 0);
|
||||
|
||||
if (!chain.IsGroup) database.GetCollection<MessageRecord>().Insert(hash, new()
|
||||
{
|
||||
FriendUin = context.BotUin,
|
||||
Sequence = result.Sequence ?? 0,
|
||||
ClientSequence = result.ClientSequence,
|
||||
Time = DateTimeOffset.FromUnixTimeSeconds(result.Timestamp).LocalDateTime,
|
||||
MessageId = result.MessageId,
|
||||
FriendInfo = new(
|
||||
context.BotUin,
|
||||
context.ContextCollection.Keystore.Uid ?? string.Empty,
|
||||
context.BotName ?? string.Empty,
|
||||
string.Empty,
|
||||
string.Empty,
|
||||
string.Empty
|
||||
),
|
||||
Entities = chain,
|
||||
MessageHash = hash,
|
||||
TargetUin = chain.FriendUin
|
||||
});
|
||||
|
||||
return new OneBotResult(new OneBotMessageResponse(hash), 0, "ok");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Message;
|
||||
|
||||
[Operation("send_poke")]
|
||||
public class SendPokeOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotSendPoke>(SerializerOptions.DefaultOptions) is { } poke)
|
||||
{
|
||||
bool result = poke.GroupId.HasValue ? await context.GroupPoke(poke.GroupId.Value, poke.UserId) : await context.FriendPoke(poke.UserId);
|
||||
return new OneBotResult(null, result ? 0 : -1, result ? "ok" : "failed");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.Core.Message;
|
||||
using Lagrange.Core.Message.Entity;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Entity.Action.Response;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
using Lagrange.OneBot.Database;
|
||||
using LiteDB;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Message;
|
||||
|
||||
[Operation("send_private_forward_msg")]
|
||||
public class SendPrivateForwardOperation(MessageCommon common, LiteDatabase database) : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotPrivateForward>(SerializerOptions.DefaultOptions) is { } forward)
|
||||
{
|
||||
var chains = common.BuildForwardChains(context, forward);
|
||||
|
||||
var multi = new MultiMsgEntity([.. chains]);
|
||||
var chain = MessageBuilder.Friend(forward.UserId).Add(multi).Build();
|
||||
|
||||
var result = await context.SendMessage(chain);
|
||||
|
||||
if (result.Result != 0) return new OneBotResult(null, (int)result.Result, "failed");
|
||||
if (result.Sequence == null || result.Sequence == 0) return new OneBotResult(null, 9000, "failed");
|
||||
|
||||
int hash = MessageRecord.CalcMessageHash(result.MessageId, result.Sequence ?? 0);
|
||||
|
||||
database.GetCollection<MessageRecord>().Insert(hash, new()
|
||||
{
|
||||
FriendUin = context.BotUin,
|
||||
Sequence = result.Sequence ?? 0,
|
||||
ClientSequence = result.ClientSequence,
|
||||
Time = DateTimeOffset.FromUnixTimeSeconds(result.Timestamp).LocalDateTime,
|
||||
MessageId = result.MessageId,
|
||||
FriendInfo = new(
|
||||
context.BotUin,
|
||||
context.ContextCollection.Keystore.Uid ?? string.Empty,
|
||||
context.BotName ?? string.Empty,
|
||||
string.Empty,
|
||||
string.Empty,
|
||||
string.Empty
|
||||
),
|
||||
Entities = chain,
|
||||
MessageHash = hash,
|
||||
TargetUin = chain.FriendUin
|
||||
});
|
||||
|
||||
return new OneBotResult(new OneBotForwardResponse(hash, multi.ResId ?? ""), 0, "ok");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Entity.Action.Response;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
using Lagrange.OneBot.Database;
|
||||
using LiteDB;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Message;
|
||||
|
||||
[Operation("send_private_msg")]
|
||||
public sealed class SendPrivateMessageOperation(MessageCommon common, LiteDatabase database) : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
var chain = payload.Deserialize<OneBotPrivateMessageBase>(SerializerOptions.DefaultOptions) switch
|
||||
{
|
||||
OneBotPrivateMessage message => common.ParseChain(message).Build(),
|
||||
OneBotPrivateMessageSimple messageSimple => common.ParseChain(messageSimple).Build(),
|
||||
OneBotPrivateMessageText messageText => common.ParseChain(messageText).Build(),
|
||||
_ => throw new Exception()
|
||||
};
|
||||
|
||||
var result = await context.SendMessage(chain);
|
||||
|
||||
if (result.Result != 0) return new OneBotResult(null, (int)result.Result, "failed");
|
||||
if (result.Sequence == null || result.Sequence == 0) return new OneBotResult(null, 9000, "failed");
|
||||
|
||||
int hash = MessageRecord.CalcMessageHash(result.MessageId, result.Sequence ?? 0);
|
||||
|
||||
database.GetCollection<MessageRecord>().Insert(hash, new()
|
||||
{
|
||||
FriendUin = context.BotUin,
|
||||
Sequence = result.Sequence ?? 0,
|
||||
ClientSequence = result.ClientSequence,
|
||||
Time = DateTimeOffset.FromUnixTimeSeconds(result.Timestamp).LocalDateTime,
|
||||
MessageId = result.MessageId,
|
||||
FriendInfo = new(
|
||||
context.BotUin,
|
||||
context.ContextCollection.Keystore.Uid ?? string.Empty,
|
||||
context.BotName ?? string.Empty,
|
||||
string.Empty,
|
||||
string.Empty,
|
||||
string.Empty
|
||||
),
|
||||
Entities = chain,
|
||||
MessageHash = hash,
|
||||
TargetUin = chain.FriendUin
|
||||
});
|
||||
|
||||
return new OneBotResult(new OneBotMessageResponse(hash), 0, "ok");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.Core.Common.Interface.Api;
|
||||
using Lagrange.Core.Message;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
using Lagrange.OneBot.Database;
|
||||
using LiteDB;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Message;
|
||||
|
||||
[Operation("set_essence_msg")]
|
||||
public class SetEssenceMessageOperation(LiteDatabase database) : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotGetMessage>(SerializerOptions.DefaultOptions) is { } getMsg)
|
||||
{
|
||||
var record = database.GetCollection<MessageRecord>().FindById(getMsg.MessageId);
|
||||
var chain = (MessageChain)record;
|
||||
bool result = await context.SetEssenceMessage(chain);
|
||||
return new OneBotResult(null, result ? 0 : 1, result ? "ok" : "failed");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Lagrange.OneBot.Core.Operation;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
|
||||
public class OperationAttribute(string api) : Attribute
|
||||
{
|
||||
public string Api => api;
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
using System.Reflection;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Network;
|
||||
using Lagrange.OneBot.Core.Notify;
|
||||
using Lagrange.OneBot.Core.Operation.Message;
|
||||
using Lagrange.OneBot.Message;
|
||||
using LiteDB;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using JsonSerializer = System.Text.Json.JsonSerializer;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation;
|
||||
|
||||
public sealed class OperationService
|
||||
{
|
||||
private readonly BotContext _bot;
|
||||
private readonly ILogger _logger;
|
||||
private readonly Dictionary<string, Type> _operations;
|
||||
private readonly ServiceProvider _service;
|
||||
|
||||
public OperationService(BotContext bot, ILogger<OperationService> logger, LiteDatabase context, MessageService message)
|
||||
{
|
||||
_bot = bot;
|
||||
_logger = logger;
|
||||
|
||||
_operations = new Dictionary<string, Type>();
|
||||
foreach (var type in Assembly.GetExecutingAssembly().GetTypes())
|
||||
{
|
||||
var attributes = type.GetCustomAttributes<OperationAttribute>();
|
||||
foreach (var attribute in attributes) _operations[attribute.Api] = type;
|
||||
}
|
||||
|
||||
var service = new ServiceCollection();
|
||||
service.AddSingleton(bot);
|
||||
service.AddSingleton(context);
|
||||
service.AddSingleton(logger);
|
||||
service.AddSingleton(message);
|
||||
service.AddSingleton<MessageCommon>();
|
||||
service.AddSingleton<TicketService>();
|
||||
service.AddLogging();
|
||||
|
||||
foreach (var (_, type) in _operations) service.AddScoped(type);
|
||||
_service = service.BuildServiceProvider();
|
||||
}
|
||||
|
||||
public async Task<OneBotResult?> HandleOperation(MsgRecvEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (JsonSerializer.Deserialize<OneBotAction>(e.Data) is { } action)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_operations.TryGetValue(action.Action, out var type))
|
||||
{
|
||||
var handler = (IOperation)_service.GetRequiredService(type);
|
||||
var result = await handler.HandleOperation(_bot, action.Params);
|
||||
result.Echo = action.Echo;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return new OneBotResult(null, 404, "failed") { Echo = action.Echo };
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Unexpected error encountered while handling message.");
|
||||
return new OneBotResult(null, 200, "failed") { Echo = action.Echo };
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Json Serialization failed for such action");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Request;
|
||||
|
||||
[Operation("set_friend_add_request")]
|
||||
public class SetFriendAddRequestOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotSetRequest>(SerializerOptions.DefaultOptions) is { } request)
|
||||
{
|
||||
bool result = await context.ContextCollection.Business.OperationLogic.SetFriendRequest(request.Flag, request.Approve);
|
||||
return new OneBotResult(null, result ? 0 : 1, "ok");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Lagrange.Core;
|
||||
using Lagrange.OneBot.Core.Entity.Action;
|
||||
using Lagrange.OneBot.Core.Operation.Converters;
|
||||
|
||||
namespace Lagrange.OneBot.Core.Operation.Request;
|
||||
|
||||
[Operation("set_group_add_request")]
|
||||
public class SetGroupAddRequestOperation : IOperation
|
||||
{
|
||||
public async Task<OneBotResult> HandleOperation(BotContext context, JsonNode? payload)
|
||||
{
|
||||
if (payload.Deserialize<OneBotSetRequest>(SerializerOptions.DefaultOptions) is { } request)
|
||||
{
|
||||
string[] split = request.Flag.Split('-');
|
||||
ulong sequence = ulong.Parse(split[0]);
|
||||
uint groupUin = uint.Parse(split[1]);
|
||||
uint eventType = uint.Parse(split[2]);
|
||||
bool isFiltered = Convert.ToBoolean(uint.Parse(split.Length > 3 ? split[3] : "0"));
|
||||
|
||||
bool result = isFiltered
|
||||
? await context.ContextCollection.Business.OperationLogic.SetGroupFilteredRequest(groupUin, sequence,
|
||||
eventType, request.Approve, request.Reason)
|
||||
: await context.ContextCollection.Business.OperationLogic.SetGroupRequest(groupUin, sequence, eventType,
|
||||
request.Approve, request.Reason);
|
||||
return new OneBotResult(null, result ? 0 : 1, "ok");
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user