Signed-off-by: Eicy <im@crash.work>
This commit is contained in:
2024-12-17 00:23:59 +08:00
commit 88abc095c2
12 changed files with 1061 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
/.idea/
/[Bb]in/
/[Oo]bj/

594
API/Api.cs Normal file
View File

@@ -0,0 +1,594 @@
// <auto-generated>
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: api.proto
// </auto-generated>
#pragma warning disable 1591, 0612, 3021, 8981
#region Designer generated code
using pb = global::Google.Protobuf;
using pbc = global::Google.Protobuf.Collections;
using pbr = global::Google.Protobuf.Reflection;
using scg = global::System.Collections.Generic;
namespace Api {
/// <summary>Holder for reflection information generated from api.proto</summary>
public static partial class ApiReflection {
#region Descriptor
/// <summary>File descriptor for api.proto</summary>
public static pbr::FileDescriptor Descriptor {
get { return descriptor; }
}
private static pbr::FileDescriptor descriptor;
static ApiReflection() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
"CglhcGkucHJvdG8SA2FwaSJGCgdSZXF1ZXN0EgwKBGNvZGUYASABKAkSDAoE",
"c3RyMRgCIAEoCRIMCgRzdHIyGAMgASgJEhEKCWludF92YWx1ZRgEIAEoBSIs",
"CghSZXNwb25zZRIPCgdzdWNjZXNzGAEgASgIEg8KB21lc3NhZ2UYAiABKAky",
"NAoKQXBpU2VydmljZRImCgdDYWxsQXBpEgwuYXBpLlJlcXVlc3QaDS5hcGku",
"UmVzcG9uc2ViBnByb3RvMw=="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
new pbr::GeneratedClrTypeInfo(typeof(global::Api.Request), global::Api.Request.Parser, new[]{ "Code", "Str1", "Str2", "IntValue" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Api.Response), global::Api.Response.Parser, new[]{ "Success", "Message" }, null, null, null, null)
}));
}
#endregion
}
#region Messages
/// <summary>
/// 定义消息结构
/// </summary>
[global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")]
public sealed partial class Request : pb::IMessage<Request>
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
, pb::IBufferMessage
#endif
{
private static readonly pb::MessageParser<Request> _parser = new pb::MessageParser<Request>(() => new Request());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pb::MessageParser<Request> Parser { get { return _parser; } }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pbr::MessageDescriptor Descriptor {
get { return global::Api.ApiReflection.Descriptor.MessageTypes[0]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public Request() {
OnConstruction();
}
partial void OnConstruction();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public Request(Request other) : this() {
code_ = other.code_;
str1_ = other.str1_;
str2_ = other.str2_;
intValue_ = other.intValue_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public Request Clone() {
return new Request(this);
}
/// <summary>Field number for the "code" field.</summary>
public const int CodeFieldNumber = 1;
private string code_ = "";
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public string Code {
get { return code_; }
set {
code_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
/// <summary>Field number for the "str1" field.</summary>
public const int Str1FieldNumber = 2;
private string str1_ = "";
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public string Str1 {
get { return str1_; }
set {
str1_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
/// <summary>Field number for the "str2" field.</summary>
public const int Str2FieldNumber = 3;
private string str2_ = "";
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public string Str2 {
get { return str2_; }
set {
str2_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
/// <summary>Field number for the "int_value" field.</summary>
public const int IntValueFieldNumber = 4;
private int intValue_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public int IntValue {
get { return intValue_; }
set {
intValue_ = value;
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override bool Equals(object other) {
return Equals(other as Request);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public bool Equals(Request other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (Code != other.Code) return false;
if (Str1 != other.Str1) return false;
if (Str2 != other.Str2) return false;
if (IntValue != other.IntValue) return false;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override int GetHashCode() {
int hash = 1;
if (Code.Length != 0) hash ^= Code.GetHashCode();
if (Str1.Length != 0) hash ^= Str1.GetHashCode();
if (Str2.Length != 0) hash ^= Str2.GetHashCode();
if (IntValue != 0) hash ^= IntValue.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void WriteTo(pb::CodedOutputStream output) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
output.WriteRawMessage(this);
#else
if (Code.Length != 0) {
output.WriteRawTag(10);
output.WriteString(Code);
}
if (Str1.Length != 0) {
output.WriteRawTag(18);
output.WriteString(Str1);
}
if (Str2.Length != 0) {
output.WriteRawTag(26);
output.WriteString(Str2);
}
if (IntValue != 0) {
output.WriteRawTag(32);
output.WriteInt32(IntValue);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
if (Code.Length != 0) {
output.WriteRawTag(10);
output.WriteString(Code);
}
if (Str1.Length != 0) {
output.WriteRawTag(18);
output.WriteString(Str1);
}
if (Str2.Length != 0) {
output.WriteRawTag(26);
output.WriteString(Str2);
}
if (IntValue != 0) {
output.WriteRawTag(32);
output.WriteInt32(IntValue);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(ref output);
}
}
#endif
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public int CalculateSize() {
int size = 0;
if (Code.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Code);
}
if (Str1.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Str1);
}
if (Str2.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Str2);
}
if (IntValue != 0) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(IntValue);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(Request other) {
if (other == null) {
return;
}
if (other.Code.Length != 0) {
Code = other.Code;
}
if (other.Str1.Length != 0) {
Str1 = other.Str1;
}
if (other.Str2.Length != 0) {
Str2 = other.Str2;
}
if (other.IntValue != 0) {
IntValue = other.IntValue;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(pb::CodedInputStream input) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
input.ReadRawMessage(this);
#else
uint tag;
while ((tag = input.ReadTag()) != 0) {
if ((tag & 7) == 4) {
// Abort on any end group tag.
return;
}
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
Code = input.ReadString();
break;
}
case 18: {
Str1 = input.ReadString();
break;
}
case 26: {
Str2 = input.ReadString();
break;
}
case 32: {
IntValue = input.ReadInt32();
break;
}
}
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
if ((tag & 7) == 4) {
// Abort on any end group tag.
return;
}
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
break;
case 10: {
Code = input.ReadString();
break;
}
case 18: {
Str1 = input.ReadString();
break;
}
case 26: {
Str2 = input.ReadString();
break;
}
case 32: {
IntValue = input.ReadInt32();
break;
}
}
}
}
#endif
}
[global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")]
public sealed partial class Response : pb::IMessage<Response>
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
, pb::IBufferMessage
#endif
{
private static readonly pb::MessageParser<Response> _parser = new pb::MessageParser<Response>(() => new Response());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pb::MessageParser<Response> Parser { get { return _parser; } }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pbr::MessageDescriptor Descriptor {
get { return global::Api.ApiReflection.Descriptor.MessageTypes[1]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public Response() {
OnConstruction();
}
partial void OnConstruction();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public Response(Response other) : this() {
success_ = other.success_;
message_ = other.message_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public Response Clone() {
return new Response(this);
}
/// <summary>Field number for the "success" field.</summary>
public const int SuccessFieldNumber = 1;
private bool success_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public bool Success {
get { return success_; }
set {
success_ = value;
}
}
/// <summary>Field number for the "message" field.</summary>
public const int MessageFieldNumber = 2;
private string message_ = "";
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public string Message {
get { return message_; }
set {
message_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override bool Equals(object other) {
return Equals(other as Response);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public bool Equals(Response other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (Success != other.Success) return false;
if (Message != other.Message) return false;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override int GetHashCode() {
int hash = 1;
if (Success != false) hash ^= Success.GetHashCode();
if (Message.Length != 0) hash ^= Message.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void WriteTo(pb::CodedOutputStream output) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
output.WriteRawMessage(this);
#else
if (Success != false) {
output.WriteRawTag(8);
output.WriteBool(Success);
}
if (Message.Length != 0) {
output.WriteRawTag(18);
output.WriteString(Message);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
if (Success != false) {
output.WriteRawTag(8);
output.WriteBool(Success);
}
if (Message.Length != 0) {
output.WriteRawTag(18);
output.WriteString(Message);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(ref output);
}
}
#endif
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public int CalculateSize() {
int size = 0;
if (Success != false) {
size += 1 + 1;
}
if (Message.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Message);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(Response other) {
if (other == null) {
return;
}
if (other.Success != false) {
Success = other.Success;
}
if (other.Message.Length != 0) {
Message = other.Message;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(pb::CodedInputStream input) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
input.ReadRawMessage(this);
#else
uint tag;
while ((tag = input.ReadTag()) != 0) {
if ((tag & 7) == 4) {
// Abort on any end group tag.
return;
}
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
Success = input.ReadBool();
break;
}
case 18: {
Message = input.ReadString();
break;
}
}
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
if ((tag & 7) == 4) {
// Abort on any end group tag.
return;
}
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
break;
case 8: {
Success = input.ReadBool();
break;
}
case 18: {
Message = input.ReadString();
break;
}
}
}
}
#endif
}
#endregion
}
#endregion Designer generated code

21
API/api.proto Normal file
View File

@@ -0,0 +1,21 @@
syntax = "proto3";
package api;
// 定义消息结构
message Request {
string code = 1;
string str1 = 2;
string str2 = 3;
int32 int_value = 4;
}
message Response {
bool success = 1;
string message = 2;
}
// 定义服务
service ApiService {
rpc CallApi (Request) returns (Response);
}

2
ApiS.cs Normal file
View File

@@ -0,0 +1,2 @@
namespace Shrink;

156
Command/Commands.cs Normal file
View File

@@ -0,0 +1,156 @@
using System.Text.Json;
using System.Xml;
using Lagrange.Core;
using Lagrange.Core.Common.Interface.Api;
using Lagrange.Core.Message;
using Shrink.Login;
namespace Shrink.Command;
public class Commands
{
private static Commands? _instance;
private static readonly object Lock = new();
private Commands() { }
public static Commands Instance
{
get
{
if (_instance != null) return _instance;
lock (Lock)
{
_instance ??= new Commands();
}
return _instance;
}
}
// 使用字典存储命令和群消息
private Dictionary<string, string> _commandDict = new();
private List<string> _corpus = new();
private Dictionary<uint, string> _messageDict = new();
private HashSet<uint> _adminSet = new();
// 文件初始化
public async Task Init()
{
// 读取Admins.json
if (File.Exists("Admins.json"))
{
_adminSet = new HashSet<uint>(JsonSerializer.Deserialize<List<uint>>(await File.ReadAllTextAsync("Admins.json")));
}
else
{
_adminSet.Add(3048536893); // 默认管理员
await File.WriteAllTextAsync("Admins.json", JsonSerializer.Serialize(_adminSet.ToList()));
}
// 读取JoinMessage.json
if (File.Exists("JoinMessage.json"))
{
_messageDict = JsonSerializer.Deserialize<List<KeyValuePair<uint, string>>>(await File.ReadAllTextAsync("JoinMessage.json"))
.ToDictionary(msg => msg.Key, msg => msg.Value);
}
else
{
_messageDict.Add(620902312, "欢迎");
await File.WriteAllTextAsync("JoinMessage.json", JsonSerializer.Serialize(_messageDict.Select(kv => new KeyValuePair<uint, string>(kv.Key, kv.Value)).ToList()));
}
// 读取Commands.json
if (File.Exists("Commands.json"))
{
_commandDict = JsonSerializer.Deserialize<List<KeyValuePair<string, string>>>(await File.ReadAllTextAsync("Commands.json"))
.ToDictionary(cmd => cmd.Key, cmd => cmd.Value);
}
else
{
_commandDict.Add("/ping", "Pong!");
await File.WriteAllTextAsync("Commands.json", JsonSerializer.Serialize(_commandDict.Select(kv => new KeyValuePair<string, string>(kv.Key, kv.Value)).ToList()));
}
}
private async Task SaveAdmin()
{
await File.WriteAllTextAsync("Admins.json", JsonSerializer.Serialize(_adminSet.ToList()));
await Init();
}
// bot管理员权限检查
private void NoEnoughPermission(BotContext ctx, uint groupID)
{
var chain = MessageBuilder.Group(groupID).Text("权限不足");
ctx.SendMessage(chain.Build());
}
// 先Init后再运行
public Task Run()
{
QrCode.Instance.Client.Invoker.OnGroupMemberIncreaseEvent += (context, @event) =>
{
var groupid = @event.GroupUin;
if (_messageDict.ContainsKey(groupid))
{
var message = _messageDict[groupid];
var chain = MessageBuilder.Group(groupid).Text(message);
context.SendMessage(chain.Build());
}
};
QrCode.Instance.Client.Invoker.OnGroupMessageReceived += (content, @event) =>
{
var groupId = @event.Chain.GroupUin.Value;
var senderId = @event.Chain.FriendUin;
var text = @event.Chain.ToPreviewText();
// 执行命令
if (_commandDict.ContainsKey(text))
{
var chain = MessageBuilder.Group(groupId).Text(_commandDict[text]);
content.SendMessage(chain.Build());
}
var today = DateTime.Today;
var seed = today.Year ^ today.Month ^ today.Day ^ senderId;
var random = new Random((int)seed);
switch (text)
{
case "/reload":
_ = Init();
var chain3 = MessageBuilder.Group(groupId).Text("重载完成!");
content.SendMessage(chain3.Build());
break;
}
if (text.Contains("/addadmin") && text.StartsWith("/addadmin"))
{
if (_adminSet.Contains(senderId))
{
var temp = uint.Parse(text.Remove(0, 9));
if (_adminSet.Contains(temp))
{
var chain = MessageBuilder.Group(groupId).Text("已存在管理员: " + temp);
content.SendMessage(chain.Build());
}
else
{
_adminSet.Add(temp);
var chain = MessageBuilder.Group(groupId).Text("已添加管理员: " + temp);
SaveAdmin();
content.SendMessage(chain.Build());
}
}
else
{
NoEnoughPermission(content, groupId);
}
}
};
return Task.CompletedTask;
}
}

106
Login/QrCode.cs Normal file
View File

@@ -0,0 +1,106 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using Lagrange.Core;
using Lagrange.Core.Common;
using Lagrange.Core.Common.Interface;
using Lagrange.Core.Common.Interface.Api;
using Shrink.Utility;
using Console = System.Console;
namespace Shrink.Login;
public class QrCode
{
private static QrCode? _instance;
private static readonly object Lock = new();
public static QrCode Instance
{
get
{
// 双重检查锁定
if (_instance != null) return _instance;
lock (Lock)
{
_instance ??= new QrCode();
}
return _instance;
}
}
public BotContext? Client;
public static void SaveKeystore(BotKeystore keystore) =>
File.WriteAllText("Keystore.json", JsonSerializer.Serialize(keystore));
public static BotDeviceInfo GetDeviceInfo()
{
if (File.Exists("DeviceInfo.json"))
{
var info = JsonSerializer.Deserialize<BotDeviceInfo>(File.ReadAllText("DeviceInfo.json"));
if (info != null) return info;
info = BotDeviceInfo.GenerateInfo();
File.WriteAllText("DeviceInfo.json", JsonSerializer.Serialize(info));
return info;
}
var deviceInfo = BotDeviceInfo.GenerateInfo();
File.WriteAllText("DeviceInfo.json", JsonSerializer.Serialize(deviceInfo));
return deviceInfo;
}
public static BotKeystore? LoadKeystore()
{
try
{
var text = File.ReadAllText("Keystore.json");
return JsonSerializer.Deserialize<BotKeystore>(text, new JsonSerializerOptions()
{
ReferenceHandler = ReferenceHandler.Preserve
});
}
catch
{
return null;
}
}
// 登录方法
public async Task Login()
{
#region bot实例化
var deviceInfo = GetDeviceInfo();
var keyStore = LoadKeystore() ?? new BotKeystore();
Client = BotFactory.Create(new BotConfig
{
UseIPv6Network = false,
GetOptimumServer = true,
AutoReconnect = true,
Protocol = Protocols.Linux
}, deviceInfo, keyStore);
#endregion
// Log模式
Client.Invoker.OnBotLogEvent += (_, @event) =>
{
@event.Level.ChangeColorByTitle();
Console.WriteLine(@event.ToString());
};
// bot信息保存但存在bug未修复
Client.Invoker.OnBotOnlineEvent += (_, @event) =>
{
Console.WriteLine(@event.ToString());
SaveKeystore(Client.UpdateKeystore());
};
// 二维码生成启动后在根目录下生成qr.png
var qrCode = await Client.FetchQrCode();
if (qrCode != null)
{
await File.WriteAllBytesAsync("qr.png", qrCode.Value.QrCode);
await Client.LoginByQrCode();
}
}
}

62
Program.cs Normal file
View File

@@ -0,0 +1,62 @@
using Grpc.Net.Client;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Shrink.Command;
using Shrink.Login;
namespace Shrink;
public static class Program
{
public static async Task Main()
{
/*var originalAssemblyPath = "Lagrange.Core.dll";
var tempAssemblyPath = "ModifiedExternalAssembly.dll";
var oldUrl = "自己找";
var newUrl = "自己找";
ModifyAssembly(originalAssemblyPath, tempAssemblyPath, oldUrl, newUrl);*/
await QrCode.Instance.Login();
await Commands.Instance.Init();
await Commands.Instance.Run();
}
/*private static void ModifyAssembly(string originalAssemblyPath, string tempAssemblyPath, string oldUrl, string newUrl)
{
var assembly = AssemblyDefinition.ReadAssembly(originalAssemblyPath);
var module = assembly.MainModule;
// 查找LinuxSigner类型
var linuxSignerType = module.Types.FirstOrDefault(t => t.Name == "LinuxSigner");
if (linuxSignerType == null)
{
Console.WriteLine("无LinuxSigner类型");
return;
}
// 查找构造函数
var constructor = linuxSignerType.Methods.FirstOrDefault(m => m.IsConstructor);
if (constructor == null)
{
Console.WriteLine("无构造函数");
return;
}
var ilProcessor = constructor.Body.GetILProcessor();
foreach (var instruction in constructor.Body.Instructions)
{
// 检查是否是加载字符串操作
if (instruction.OpCode == OpCodes.Ldstr && instruction.Operand is string str && str == oldUrl)
{
instruction.Operand = newUrl; // 替换为新URL
Console.WriteLine($"替换: {oldUrl}为{newUrl}");
}
}
assembly.Write(tempAssemblyPath);
Console.WriteLine($"已将修改后的程序集保存在{tempAssemblyPath}");
}*/
}

12
README.md Normal file
View File

@@ -0,0 +1,12 @@
# ShrinkSharp
.NET6
打包为Linux可执行文件请在项目文件夹下打开控制台输入<code>dotnet publish -c Release -r linux-x64</code>
一代: https://github.com/bingling-sama/BakaHDT
二代: https://github.com/GBLodb/ChlorineSharp
三代: https://github.com/cneicy/Shrink
四代: https://github.com/cneicy/ShrinkSharp

30
Shrink.csproj Normal file
View File

@@ -0,0 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Google.Protobuf" Version="3.29.1" />
<PackageReference Include="Grpc.AspNetCore" Version="2.67.0" />
<PackageReference Include="Lagrange.Core" Version="0.3.1" />
<PackageReference Include="Mono.Cecil" Version="0.11.6" />
<PackageReference Include="SSH.NET" Version="2024.2.0" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Service\**" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Remove="Service\**" />
</ItemGroup>
<ItemGroup>
<None Remove="Service\**" />
</ItemGroup>
</Project>

16
Shrink.sln Normal file
View File

@@ -0,0 +1,16 @@

Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shrink", "Shrink.csproj", "{7547D900-7445-4C83-ACAF-84C6E4B8F291}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7547D900-7445-4C83-ACAF-84C6E4B8F291}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7547D900-7445-4C83-ACAF-84C6E4B8F291}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7547D900-7445-4C83-ACAF-84C6E4B8F291}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7547D900-7445-4C83-ACAF-84C6E4B8F291}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

16
Utility/Console.cs Normal file
View File

@@ -0,0 +1,16 @@
using Lagrange.Core.Event.EventArg;
namespace Shrink.Utility;
public static class Console
{
public static void ChangeColorByTitle(this LogLevel level) => System.Console.ForegroundColor = level switch
{
LogLevel.Debug => ConsoleColor.White,
LogLevel.Verbose => ConsoleColor.DarkGray,
LogLevel.Information => ConsoleColor.Blue,
LogLevel.Warning => ConsoleColor.Yellow,
LogLevel.Fatal => ConsoleColor.Red,
_ => System.Console.ForegroundColor
};
}

43
Utility/Data.cs.disable Normal file
View File

@@ -0,0 +1,43 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using Lagrange.Core.Common;
namespace Shrink.Utility;
public static class Data
{
public static void SaveKeystore(BotKeystore keystore) =>
File.WriteAllText("Keystore.json", JsonSerializer.Serialize(keystore));
public static BotDeviceInfo GetDeviceInfo()
{
if (File.Exists("DeviceInfo.json"))
{
var info = JsonSerializer.Deserialize<BotDeviceInfo>(File.ReadAllText("DeviceInfo.json"));
if (info != null) return info;
info = BotDeviceInfo.GenerateInfo();
File.WriteAllText("DeviceInfo.json", JsonSerializer.Serialize(info));
return info;
}
var deviceInfo = BotDeviceInfo.GenerateInfo();
File.WriteAllText("DeviceInfo.json", JsonSerializer.Serialize(deviceInfo));
return deviceInfo;
}
public static BotKeystore? LoadKeystore()
{
try
{
var text = File.ReadAllText("Keystore.json");
return JsonSerializer.Deserialize<BotKeystore>(text, new JsonSerializerOptions()
{
ReferenceHandler = ReferenceHandler.Preserve
});
}
catch
{
return null;
}
}
}