using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Text; using System.Text.Json.Serialization.Metadata; using System.Threading; using System.Threading.Tasks; using JacobTechEncryption; using Luski.net.Enums.Main; using Luski.net.Interfaces; using Luski.net.JsonTypes; using Luski.net.JsonTypes.HTTP; using Luski.net.Structures.Main; using Luski.Shared.PublicServers.V1.ClientToServer.HTTP; using Luski.Shared.PublicServers.V1.Enums; using Luski.Shared.PublicServers.V1.ServerToClient.HTTP; using ChannelType = Luski.net.Enums.Main.ChannelType; namespace Luski.net; public partial class MainServer : Server { internal MainServer(string Domain, string API_Version): base(Domain, API_Version) { } public MainSocketAppUser User { get; internal set; } = default!; public List chans { get; } = new(); public async Task SendFriendResult(long user, bool answer, CancellationToken CancellationToken) { FriendRequestResult json = await SendServer("FriendRequestResult", new FriendRequestResultOut() { Id = user, Result = answer }, FriendRequestResultOutContext.Default.FriendRequestResultOut, FriendRequestResultContext.Default.FriendRequestResult, CancellationToken); if (json is not null && json.Error is null && json.ErrorMessage is null && answer && json.Channel is not null) { MainSocketDMChannel chan = await GetChannel((long)json.Channel, MainSocketDMChannelContext.Default.MainSocketDMChannel, CancellationToken); _ = chan.StartKeyProcessAsync(CancellationToken); chans.Add(chan); } else { throw new Exception(json?.Error.ToString()); } return GetUser(user, MainSocketRemoteUserContext.Default.MainSocketRemoteUser, CancellationToken).Result; } public async Task SendFriendRequest(long code, CancellationToken CancellationToken) { string ccode = Convert.ToBase64String(Encryption.Hashing.SHA256(Encoding.Unicode.GetBytes(code.ToString()))); FriendRequestResult? json = await SendServer("FriendRequest", new FriendRequest() { code = ccode}, FriendRequestContext.Default.FriendRequest, FriendRequestResultContext.Default.FriendRequestResult, CancellationToken); if (json.StatusCode != HttpStatusCode.Accepted) { if (json is not null && json.Error is not null) { switch ((ErrorCode)(int)json.Error) { case ErrorCode.InvalidToken: throw new Exception("Your current token is no longer valid"); case ErrorCode.ServerError: throw new Exception($"Error from server: {json.ErrorMessage}"); case ErrorCode.InvalidPostData: throw new Exception("The post data dent to the server is not the correct format. This may be because you app is couropt or you are using the wron API version"); case ErrorCode.Forbidden: throw new Exception("You already have an outgoing request or the persone is not real"); } } if (json is not null && json.Channel is not null) { MainSocketDMChannel chan = await GetChannel((long)json.Channel, MainSocketDMChannelContext.Default.MainSocketDMChannel, CancellationToken); _ = chan.StartKeyProcessAsync(CancellationToken); chans.Add(chan); } } MainSocketRemoteUser b = await GetUser(code, MainSocketRemoteUserContext.Default.MainSocketRemoteUser, CancellationToken); if (json.Channel is not null) b.FriendStatus = FriendStatus.Friends; else b.FriendStatus = FriendStatus.PendingOut; return b; } public async Task GetChannel(long Channel, CancellationToken CancellationToken) where TChannel : MainSocketChannel, new() { TChannel Return = new(); switch (Return) { case MainSocketDMChannel: Return = (await GetChannel(Channel, MainSocketDMChannelContext.Default.MainSocketDMChannel, CancellationToken) as TChannel)!; break; case MainSocketGroupChannel: Return = (await GetChannel(Channel, MainSocketGroupChannelContext.Default.MainSocketGroupChannel, CancellationToken) as TChannel)!; break; case MainSocketTextChannel: Return = (await GetChannel(Channel, MainSocketTextChannelContext.Default.MainSocketTextChannel, CancellationToken) as TChannel)!; break; case MainSocketChannel: Return = (await GetChannel(Channel, MainSocketChannelContext.Default.MainSocketChannel, CancellationToken) as TChannel)!; break; case null: throw new NullReferenceException(nameof(TChannel)); default: throw new Exception("Unknown channel type"); } return Return; } internal async Task GetChannel(long id, JsonTypeInfo Json, CancellationToken CancellationToken) where TChannel : MainSocketChannel, new() { TChannel request; if (chans.Count > 0 && chans.Any(s => s.Id == id)) { return (chans.Where(s => s is TChannel && s.Id == id).First() as TChannel)!; } while (true) { if (CanRequest) { request = await GetFromServer($"SocketChannel/Get/{id}", Json, CancellationToken); break; } } if (request is null) throw new Exception("Something was wrong with the server responce"); if (request.Error is null) { if (chans.Count > 0 && chans.Any(s => s.Id == request.Id)) { foreach (MainSocketChannel? p in chans.Where(s => s.Id == request.Id)) { chans.Remove(p); } } request.Server = this; chans.Add(request); return request; } throw request.Error switch { ErrorCode.InvalidToken => new Exception("Your current token is no longer valid"), ErrorCode.Forbidden => new Exception("The server rejected your request"), ErrorCode.ServerError => new Exception("Error from server: " + request.ErrorMessage), ErrorCode.InvalidURL or ErrorCode.MissingHeader => new Exception(request.ErrorMessage), _ => new Exception($"Unknown data: '{request.ErrorMessage}'"), }; } public Task GetUser(long UserID, CancellationToken CancellationToken) where Tuser : MainSocketUserBase, new() { Tuser user = new(); switch (user) { case MainSocketAppUser: user = (GetUser(UserID, MainSocketAppUserContext.Default.MainSocketAppUser, CancellationToken).Result as Tuser)!; break; case MainSocketRemoteUser: user = (GetUser(UserID, MainSocketRemoteUserContext.Default.MainSocketRemoteUser, CancellationToken).Result as Tuser)!; break; case MainSocketUserBase: user = (GetUser(UserID, MainSocketUserBaseContext.Default.MainSocketUserBase, CancellationToken).Result as Tuser)!; break; case null: throw new NullReferenceException(nameof(Tuser)); default: throw new Exception("Unknown channel type"); } return Task.FromResult(user); } public async Task GetMessage(long id, CancellationToken CancellationToken) { MainSocketMessage message; while (true) { if (CanRequest) { message = await GetFromServer("socketmessage", MainSocketMessageContext.Default.MainSocketMessage, CancellationToken, new KeyValuePair("msg_id", id.ToString())); break; } } if (message is not null) { message.Server = this; return message; } throw new Exception("Server did not return a message"); } /// /// Sends the server a request to update the of you account /// /// The you want to set your status to /// public async Task UpdateStatus(UserStatus Status, CancellationToken CancellationToken) { STC? data = await SendServer("SocketUserProfile/Status", new StatusUpdateCTS() { Status = Status }, StatusUpdateCTSContext.Default.StatusUpdateCTS, STCContext.Default.STC, CancellationToken); if (data.Error is not null && ((int)data.StatusCode < 200 || (int)data.StatusCode > 299)) { if (data?.ErrorMessage is not null) throw new Exception(data.ErrorMessage); if (data?.Error is not null) throw new Exception(((int)data.Error).ToString()); else throw new Exception("Something went worng"); } User.Status = Status; return Task.CompletedTask; } internal async Task GetUser(long UserId, JsonTypeInfo Json, CancellationToken CancellationToken) where Tuser : MainSocketUserBase, new() { Tuser user; if (poeople.Count > 0 && poeople.Any(s => s.Id == UserId)) { Tuser temp = poeople.Where(s => s is Tuser && s.Id == UserId).Cast().FirstOrDefault()!; if (temp is MainSocketRemoteUser && (temp as MainSocketRemoteUser)!.Channel == null) { foreach (MainSocketDMChannel chan in chans.Where(s => s is MainSocketDMChannel).Cast()) { if (chan.Type == ChannelType.DM && chan.Id != 0 && chan.MemberIdList is not null) { if (chan.MemberIdList.Any(s => s == UserId)) (temp as MainSocketRemoteUser)!.Channel = chan; } } } return temp; } while (true) { if (CanRequest) { user = await GetFromServer("socketuser", Json, CancellationToken, new KeyValuePair("id", UserId.ToString())); break; } } if (user is null) throw new Exception("Server did not return a user"); if (poeople.Count > 0 && poeople.Any(s => s.Id == UserId)) { foreach (IUser? p in poeople.Where(s => s.Id == UserId)) { poeople.Remove(p); } } user.Server = this; if (user is MainSocketRemoteUser && (user as MainSocketRemoteUser)!.Channel == null) { foreach (MainSocketDMChannel chan in chans.Where(s => s is MainSocketDMChannel).Cast()) { if (chan.Type == ChannelType.DM && chan.Id != 0 && chan.MemberIdList is not null) { if (chan.MemberIdList.Any(s => s == UserId)) (user as MainSocketRemoteUser)!.Channel = chan; } } } poeople.Add(user); return user; } }