2023-08-21 10:58:17 -04:00
using System ;
using System.Collections.Generic ;
using System.Linq ;
2023-08-25 12:07:36 -04:00
using System.Net.Http ;
2023-08-21 10:58:17 -04:00
using System.Text ;
using System.Text.Json.Serialization.Metadata ;
using System.Threading ;
using System.Threading.Tasks ;
using JacobTechEncryption ;
using JacobTechEncryption.Enums ;
using Luski.net.Enums ;
using Luski.net.Enums.Main ;
using Luski.net.Interfaces ;
using Luski.net.JsonTypes ;
using Luski.net.JsonTypes.BaseTypes ;
using Luski.net.JsonTypes.HTTP ;
using Luski.net.JsonTypes.Public ;
using Luski.net.Structures ;
using Luski.net.Structures.Public ;
using Channel = Luski . net . JsonTypes . Public . Channel ;
using Role = Luski . net . Structures . Public . Role ;
using SocketUser = Luski . net . Structures . Public . SocketUser ;
2023-07-08 09:06:13 -04:00
namespace Luski.net ;
2023-08-21 10:58:17 -04:00
public partial class PublicServer : Server
2023-07-08 09:06:13 -04:00
{
2023-08-21 10:58:17 -04:00
public List < SocketChannel > chans { get ; } = new ( ) ;
public List < SocketCategory > cats { get ; } = new ( ) ;
public List < Role > roles { get ; } = new ( ) ;
public SocketAppUser User { get ; private set ; } = null ! ;
2023-08-25 12:07:36 -04:00
2023-10-01 13:12:27 -04:00
private PublicServer ( string Domain , string API_Version , bool Secure = true ) :
base ( Domain , API_Version , Secure )
2023-08-25 12:07:36 -04:00
{ }
2023-10-01 13:12:27 -04:00
internal static async Task < PublicServer > GetServer ( string Domain , string API_Version , bool Secure = true )
2023-08-21 10:58:17 -04:00
{
2023-08-25 12:07:36 -04:00
DateTime dt = DateTime . UtcNow ;
Console . WriteLine ( "Connecting to public server '{0}' using API {1}." , Domain , API_Version ) ;
2023-10-01 13:12:27 -04:00
PublicServer s = new ( Domain , API_Version , Secure ) ;
2023-08-25 12:07:36 -04:00
ServerInfo ? si = null ;
try
{
si = await s . GetFromServer ( "socketserver" , ServerInfoContext . Default . ServerInfo , CancellationToken . None ) ;
s . EncryptionHandler . ServerPublicKey = await ( await new HttpClient ( )
. GetAsync ( $"{(s.Secure ? " https " : " http ")}://{s.Domain}/{s.ApiVersion}/Keys/PublicKey" ) )
. Content
. ReadAsStringAsync ( ) ;
}
catch ( Exception e )
{
LocalServerInfo ServerListing = s . Storage . GetJson ( StorageDirectory . ServerInfo , "Servers.json" , true ,
LocalServerInfoContext . Default . LocalServerInfo ) ;
if ( ServerListing . AlternateServers . Length > 0 )
{
Console . WriteLine ( "Failed to connect to public server '{0}' using API {1}. Attempting to connect to alternate servers." , Domain , API_Version ) ;
foreach ( ServerData Server in ServerListing . AlternateServers )
{
s . Secure = Server . Secure ;
s . Domain = Server . DomainAndPort ;
try
{
si = await s . GetFromServer ( "socketserver" , ServerInfoContext . Default . ServerInfo , CancellationToken . None ) ;
s . EncryptionHandler . ServerPublicKey = await ( await new HttpClient ( )
. GetAsync ( $"{(s.Secure ? " https " : " http ")}://{s.Domain}/{s.ApiVersion}/Keys/PublicKey" ) )
. Content
. ReadAsStringAsync ( ) ;
Console . WriteLine ( "Public server '{0}' connection restored by alternate server '{1}' using API {2}." , Domain , s . Domain , API_Version ) ;
break ;
}
catch
{
// ignored
}
}
}
if ( si is null ) throw ;
}
s . Name = si . name ;
s . Description = si . description ;
s . wssurl = si . wssv4 ;
s . ServerType = ServerType . Public ;
Console . WriteLine ( "Connected to public server '{0}' using API {1} in {4}.\nServer Name: {2}\nServer Description: {3}" , Domain , API_Version , s . Name , s . Description , DateTime . UtcNow . Subtract ( dt ) . ToString ( "g" ) ) ;
return s ;
2023-08-21 10:58:17 -04:00
}
public async Task < TCategory > GetCategory < TCategory > ( long id , CancellationToken CancellationToken ) where TCategory : SocketCategory , new ( )
{
Category request ;
if ( cats . Count > 0 & & cats . Any ( s = > s . ID = = id ) )
{
return ( cats . Where ( s = > s is TCategory & & s . ID = = id ) . First ( ) as TCategory ) ! ;
}
while ( true )
{
if ( CanRequest )
{
request = await GetFromServer ( $"SocketCategory" , PublicCategoryContext . Default . Category , CancellationToken , new KeyValuePair < string , string? > ( "id" , id . ToString ( ) ) ) ;
break ;
}
}
if ( request is null ) throw new Exception ( "Something was wrong with the server responce" ) ;
if ( request . Error is null )
{
if ( cats . Count > 0 & & cats . Any ( s = > s . ID = = request . ID ) )
{
foreach ( SocketCategory ? p in cats . Where ( s = > s . ID = = request . ID ) )
{
cats . Remove ( p ) ;
}
}
LocalKeyInfo deckey = EncryptionHandler . GetKey ( request . DescriptionEncryptionKey ) ;
string dec = deckey . EncryptionType switch
{
EncryptionType . RSA = > Encryption . RSA . Decrypt ( Convert . FromBase64String ( request . Description ) , deckey . Key , request . DescriptionEncoderType ) ,
EncryptionType . AES = > Encryption . Generic . Encoders [ ( short ) request . DescriptionEncoderType ] . GetString (
Encryption . AES . Decrypt ( Convert . FromBase64String ( request . Description ) , deckey . Key ) ) ,
_ = > Encryption . Generic . Encoders [ ( short ) request . DescriptionEncoderType ] . GetString ( Convert . FromBase64String ( request . Description ) )
} ;
LocalKeyInfo nkey = EncryptionHandler . GetKey ( request . TitleEncryptionKey ) ;
string n = nkey . EncryptionType switch
{
EncryptionType . RSA = > Encryption . RSA . Decrypt ( Convert . FromBase64String ( request . Name ) , nkey . Key , request . TitleEncoderType ) ,
EncryptionType . AES = > Encryption . Generic . Encoders [ ( short ) request . TitleEncoderType ] . GetString (
Encryption . AES . Decrypt ( Convert . FromBase64String ( request . Name ) , nkey . Key ) ) ,
_ = > Encryption . Generic . Encoders [ ( short ) request . TitleEncoderType ] . GetString ( Convert . FromBase64String ( request . Name ) )
} ;
TCategory bob = new ( )
{
ID = request . ID ,
ParentID = request . Parent ,
Description = dec ,
DescriptionEncoderType = request . DescriptionEncoderType ,
DescriptionEncryptionKey = request . DescriptionEncryptionKey ,
Channels = request . Channels ,
Categories = request . InnerCategories ,
Name = n ,
RoleOverides = request . RoleOverides ,
UserOverides = request . UserOverides ,
TitleEncoderType = request . TitleEncoderType ,
TitleEncryptionKey = request . TitleEncryptionKey ,
Server = this ,
Color = new ( request . Color )
} ;
cats . Add ( bob ) ;
return bob ;
}
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 async Task < Role > GetRole ( long id )
{
Role [ ] r = roles . Where ( s = > s . ID = = id ) . ToArray ( ) ;
if ( r . Length > 0 ) return r [ 0 ] ;
JsonTypes . Public . Role s = await GetFromServer ( "SocketRole?id=" + id . ToString ( ) , RoleContext . Default . Role , CancellationToken . None ) ;
Role role = new ( )
{
Server = this ,
ID = s . id ,
Color = new ( s . color ) ,
Description = s . description ,
DisplayName = s . display_name ,
MembersListID = s . members_list ,
Name = s . name ,
Index = s . index ,
ServerPermissions = s . server_permissions
} ;
roles . Add ( role ) ;
return role ;
}
public async Task < TChannel > GetChannel < TChannel > ( long id , CancellationToken CancellationToken ) where TChannel : SocketChannel , new ( )
{
Channel 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" , PublicChannelContext . Default . Channel , CancellationToken , new KeyValuePair < string , string? > ( "id" , id . ToString ( ) ) ) ;
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 ( SocketChannel ? p in chans . Where ( s = > s . ID = = request . ID ) )
{
chans . Remove ( p ) ;
}
}
LocalKeyInfo deckey = EncryptionHandler . GetKey ( request . DescriptionEncryptionKey ) ;
string dec = deckey . EncryptionType switch
{
EncryptionType . RSA = > Encryption . RSA . Decrypt ( Convert . FromBase64String ( request . Description ) , deckey . Key , request . DescriptionEncoderType ) ,
EncryptionType . AES = > Encryption . Generic . Encoders [ ( short ) request . DescriptionEncoderType ] . GetString (
Encryption . AES . Decrypt ( Convert . FromBase64String ( request . Description ) , deckey . Key ) ) ,
_ = > Encryption . Generic . Encoders [ ( short ) request . DescriptionEncoderType ] . GetString ( Convert . FromBase64String ( request . Description ) )
} ;
LocalKeyInfo nkey = EncryptionHandler . GetKey ( request . TitleEncryptionKey ) ;
string n = nkey . EncryptionType switch
{
EncryptionType . RSA = > Encryption . RSA . Decrypt ( Convert . FromBase64String ( request . Name ) , nkey . Key , request . TitleEncoderType ) ,
EncryptionType . AES = > Encryption . Generic . Encoders [ ( short ) request . TitleEncoderType ] . GetString (
Encryption . AES . Decrypt ( Convert . FromBase64String ( request . Name ) , nkey . Key ) ) ,
_ = > Encryption . Generic . Encoders [ ( short ) request . TitleEncoderType ] . GetString ( Convert . FromBase64String ( request . Name ) )
} ;
TChannel bob = new ( )
{
ID = request . ID ,
CategoryID = request . Parent ,
Description = dec ,
DescriptionEncoderType = request . DescriptionEncoderType ,
DescriptionEncryptionKey = request . DescriptionEncryptionKey ,
EncoderTypes = request . EncoderTypes ,
EncryptionKeys = request . EncryptionKeys ,
Epoch = request . Epoch ,
Name = n ,
RoleOverides = request . RoleOverides ,
UserOverides = request . UserOverides ,
Type = request . Type ,
TitleEncoderType = request . TitleEncoderType ,
TitleEncryptionKey = request . TitleEncryptionKey ,
PictureType = request . PictureType ,
Server = this ,
Color = new ( request . Color )
} ;
chans . Add ( bob ) ;
return bob ;
}
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 async Task < Tuser > GetUser < Tuser > ( long UserId , CancellationToken CancellationToken ) where Tuser : SocketUser , new ( )
{
JsonTypes . Public . SocketUser user ;
if ( poeople . Count > 0 & & poeople . Any ( s = > s . Id = = UserId ) )
{
Tuser temp = poeople . Where ( s = > s is Tuser & & s . Id = = UserId ) . Cast < Tuser > ( ) . FirstOrDefault ( ) ! ;
return temp ;
}
while ( true )
{
if ( CanRequest )
{
user = await GetFromServer ( "socketuser" ,
PublicSocketUserContext . Default . SocketUser ,
CancellationToken ,
new KeyValuePair < string , string? > ( "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 ) ;
}
}
if ( user is null | | user . Error is not null )
{
string error = "User was null" ;
if ( user is not null & & user . Error is not null ) error = $"{user.Error}: {user.ErrorMessage}" ;
throw new Exception ( $"Something went wrong getting your user information\n{error}" ) ;
}
Tuser u = new ( ) ;
if ( u is SocketUser )
{
u = new ( )
{
Server = this ,
Id = user . ID ,
DisplayName = user . DisplayName ,
PictureType = user . PictureType ,
RoleIds = user . RoleIds ,
Status = user . Status
} ;
}
else
{
u = ( new SocketAppUser ( )
{
Server = this ,
Id = user . ID ,
DisplayName = user . DisplayName ,
SelectedChannel = user . SelectedChannel ,
PictureType = user . PictureType ,
RoleIds = user . RoleIds ,
Status = user . Status ,
Username = user . Username
} as Tuser ) ! ;
}
poeople . Add ( u ) ;
return u ;
}
/// <summary>
/// Sends the server a request to update the <paramref name="Status"/> of you account
/// </summary>
/// <param name="Status">The <see cref="UserStatus"/> you want to set your status to</param>
/// <exception cref="Exception"></exception>
public async Task < Task > UpdateStatus ( UserStatus Status , CancellationToken CancellationToken )
2023-07-10 14:19:03 -04:00
{
2023-08-21 10:58:17 -04:00
IncomingHTTP ? data = await SendServer ( "SocketUserProfile/Status" , new Status ( ) { UserStatus = Status } , StatusContext . Default . Status , IncomingHTTPContext . Default . IncomingHTTP , 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 ;
2023-07-10 14:19:03 -04:00
}
2023-08-21 10:58:17 -04:00
2023-08-25 12:07:36 -04:00
public string Name { get ; private set ; }
public string Description { get ; private set ; }
2023-07-08 09:06:13 -04:00
}