using LiteDB; using Newtonsoft.Json; using WebSocketSharp; using WebSocketSharp.Server; using Tesses.WebServer; using Chatr; using System.Collections.Generic; using System; using System.Linq; using System.Net.Http; namespace Tesses.Chatr.Server { public static class DataBase { private const string SessionCollectionName = "Sessions"; private const string AccountCollectionName="Accounts"; private const string MessageCollectionName="Messages"; private const string NotificationCollectionName="Notifications"; private const string BotCollectionName = "Bots"; private static LiteDatabase _db; public static void SetDb(string path) { _db=new LiteDatabase(path); Accounts=_db.GetCollection(AccountCollectionName); Sessions=_db.GetCollection(SessionCollectionName); Messages=_db.GetCollection(MessageCollectionName); Bots=_db.GetCollection(BotCollectionName); Notifications=_db.GetCollection(NotificationCollectionName); } public static ILiteCollection Notifications {get;private set;} public static ILiteCollection Accounts {get;private set;} public static ILiteCollection Sessions {get;private set;} public static ILiteCollection Messages {get;private set;} //public static ILiteCollection? Messages {get;private set;} public static ILiteCollection Bots {get;private set;} public static void Dispose() { _db?.Dispose(); } } public class WSConnection : WebSocketBehavior { private Account account; private Bot bot; protected override void OnClose(CloseEventArgs e) { if(bot != null) { UserManagement.Bots[bot.Id].Remove(this); } if(account != null) { UserManagement.Humans[account.Id].Remove(this); } } private void Send(ChatrWSMsg msg) { if(this.ConnectionState == WebSocketState.Open) { try{ Send(JsonConvert.SerializeObject(msg)); }catch(Exception ex) { _=ex; } } } protected override void OnMessage(MessageEventArgs e) { if(e.IsText) { var chattrMsg=JsonConvert.DeserializeObject(e.Data); if(chattrMsg!=null){ IPacketData packet; if(chattrMsg.IsType(PacketType.ClearAll,out packet)) { if(account != null && bot == null) { var clrAll=(ClearAllPacket)packet; string[] p=clrAll.UserStr.Split(new char[]{'-'},2,StringSplitOptions.RemoveEmptyEntries); if(p.Length < 1) return; string human_name = p[0]== "me" ? account.Username : p[0]; if(p.Length ==1) { //its human foreach(var msg in UserManagement.GetMessages(account,human_name).ToList()) { DataBase.Messages.Delete(msg.Id); } if(p[0] != "me") { //we send clear all message to other person ClearAllPacket pkt=new ClearAllPacket(); pkt.UserStr=account.Username; UserManagement.SendClearAll(pkt); } }else{ //its a bot foreach(var msg in UserManagement.GetMessages(account,human_name,p[1]).ToList()) { DataBase.Messages.Delete(msg.Id); } } } } if(chattrMsg.IsType(PacketType.NotificationEventFire,out packet)) { if(account != null && bot == null) { var noFire=(NotificationEventFirePacket)packet; Console.WriteLine(JsonConvert.SerializeObject(noFire)); noFire.DestinationUserName = account.Username; UserManagement.HandleNotificationEventFirePacket(noFire); } } if(chattrMsg.IsType(PacketType.Notification,out packet)) { if(bot == null || !bot.Permissions.CanSendNotifications || account != null) return; //users can't send notifications var notification = (NotificationPacket)packet; if(notification.UserName != "me" && !bot.Permissions.CanSendMessagesToOtherPeople) return; if(DataBase.Accounts != null && DataBase.Notifications != null && notification != null && !string.IsNullOrWhiteSpace(notification.UserName)) { var bUser = DataBase.Accounts.FindById(bot.UserId); if(bUser != null){ long destId = notification.UserName == "me" ? bot.UserId : UserManagement.GetUserId(notification.UserName); var not= DataBase.Notifications.FindOne(ee=>ee.SourceBotId == bot.Id && ee.SourceUserId == bot.UserId && ee.BotNotificationId == notification.BotNotificationId); if(not != null) { if(!string.IsNullOrWhiteSpace(notification.Body)) { not.Body=notification.Body; }else{ not.Body=""; } not.NotificationButtons.Clear(); foreach(var item in notification.NotificationButtons) { not.NotificationButtons.Add(item); } not.OnClick=notification.OnClick; if(!string.IsNullOrWhiteSpace(notification.Title)) { not.Title=notification.Title; }else{ not.Title = ""; } bool isMe = notification.UserName == "me"; string botowneruserName= isMe ? "me" : bUser.Username; string botusername = bot.BotUserName; not.BotUserString = $"{botowneruserName}-{botusername}"; DataBase.Notifications.Update(not); } else { Console.WriteLine("NN"); not=new Notification(); if(!string.IsNullOrWhiteSpace(notification.Body)) { not.Body=notification.Body; }else{ not.Body=""; } not.NotificationButtons.Clear(); foreach(var item in notification.NotificationButtons) { not.NotificationButtons.Add(item); } not.OnClick=notification.OnClick; if(!string.IsNullOrWhiteSpace(notification.Title)) { not.Title=notification.Title; }else{ not.Title = ""; } if(!string.IsNullOrWhiteSpace(notification.BotNotificationId)) { not.BotNotificationId=notification.BotNotificationId; } else{ not.BotNotificationId=""; } not.SourceBotId = bot.Id; not.SourceUserId = bot.UserId; not.DestinationUserId=destId; bool isMe = notification.UserName == "me"; string botowneruserName= isMe ? "me" : bUser.Username; string botusername = bot.BotUserName; not.BotUserString = $"{botowneruserName}-{botusername}"; var bson=DataBase.Notifications.Insert(not); not.Id=bson.AsInt64; notification.Id=bson.AsInt64; } UserManagement.SendNotification(not); } } } if(chattrMsg.IsType(PacketType.AuthenticateUser,out packet)) { var authUser=(AuthenticationUserPacket)packet; //authenticate this as a user var res=UserManagement.Authenticate(authUser.SessionId); if(res.Success && res.Account !=null) { UserManagement.Humans.Add(res.Account.Id,this); account=res.Account; }else{ } } if(chattrMsg.IsType(PacketType.AuthenticateBot,out packet)) { var authUser=(AuthenticateBotPacket)packet; //authenticate this as a user var res=UserManagement.AuthenticateApiKey(authUser.ApiKey); if(res.Success && res.Bot !=null) { UserManagement.Bots.Add(res.Bot.Id,this); bot=res.Bot; } } if(chattrMsg.IsType(PacketType.Message,out packet)) { var msg = (MessagePacket)packet; if(!string.IsNullOrWhiteSpace(msg.UserStr)){ var usrs=msg.UserStr.Split(new char[]{'-'},2); if(usrs.Length >= 1) { string user = usrs[0]; string bot=null; if(usrs.Length == 2) { bot = usrs[1]; } Message msg0=new Message(); if(msg0.CreationTime.Year == 1970) msg0.CreationTime=DateTime.Now; if(!string.IsNullOrWhiteSpace(msg.Content)) msg0.Content = msg.Content; else msg0.Content = "[No Body]"; if(this.bot != null) { msg0.IsFromBot=true; msg0.SourceBotId = this.bot.Id; msg0.SourceUserId = this.bot.UserId; if(!string.IsNullOrWhiteSpace(bot)) { msg0.IsToBot=true; if(!this.bot.Permissions.OthersCanReceiveMessages) return; if(user == "me") { msg0.DestinationUserId = msg0.SourceUserId; msg0.DestinationBotId = UserManagement.GetBotId(msg0.SourceUserId,bot); }else{ msg0.DestinationUserId= UserManagement.GetUserId(user); msg0.DestinationBotId= UserManagement.GetBotId(user,bot); } UserManagement.SendMessage(msg0); }else{ msg0.IsToBot=false; if(user == "me") { msg0.DestinationUserId=msg0.SourceUserId; }else{ if(!this.bot.Permissions.CanSendMessagesToOtherPeople) return; msg0.DestinationUserId= UserManagement.GetUserId(user); } UserManagement.SendMessage(msg0); } } if(this.account != null) { msg0.IsFromBot=false; msg0.SourceUserId = this.account.Id; if(!string.IsNullOrWhiteSpace(bot)) { msg0.IsToBot=true; if(user == "me") { msg0.DestinationUserId = msg0.SourceUserId; msg0.DestinationBotId= UserManagement.GetBotId(msg0.DestinationUserId,bot); }else{ msg0.DestinationUserId= UserManagement.GetUserId(user); msg0.DestinationBotId= UserManagement.GetBotId(user,bot); } Bot bt; if(DataBase.Bots != null && (bt=DataBase.Bots.FindById(msg0.DestinationBotId)) != null) { if(!bt.Permissions.CanGetMessages) { return; } } UserManagement.SendMessage(msg0); }else{ msg0.IsToBot=false; if(user == "me") { msg0.DestinationUserId=msg0.SourceUserId; }else{ msg0.DestinationUserId= UserManagement.GetUserId(user); } UserManagement.SendMessage(msg0); } } } } } } } } public void Push(ClearAllPacket pkt) { Send(new ChatrWSMsg(pkt)); } public void Push(Message msg) { var userStr = UserManagement.GetHashTextFromMessage(msg,true); var nameStr = UserManagement.GetNameTextFromMessage(msg,true); var msgData = msg.Content; var creationTime = msg.CreationTime.ToString("R"); ChatrWSMsg packet=new ChatrWSMsg(); var mpd=new MessagePacket(); mpd.Content=msgData; mpd.CreationTime=creationTime; mpd.UserStr=userStr; mpd.Name=nameStr; //mpd.Name packet.SetPacketData(mpd); //the json packet Send(packet); } public void Push(NotificationEventFirePacket packet) { var ppacket=new ChatrWSMsg(); ppacket.SetPacketData(packet); Send(ppacket); } public void Push(Notification notification) { if(DataBase.Bots==null || DataBase.Accounts == null) return; /* object packet=new{ PacketType="Notification", Data=new{ BotName = notification.BotName, Title=notification.Title, Body=notification.Body, OnClick=notification.OnClick.ToObject(notification.Id), } }; //the json packet Send(packet); */ NotificationPacket packet=new NotificationPacket(); packet.Body=notification.Body; var bot = DataBase.Bots.FindOne(e=>e.Id==notification.SourceBotId); var usr = DataBase.Accounts.FindOne(e=>e.Id ==notification.SourceUserId); if(bot != null && usr != null) { packet.BotName = bot.BotName; packet.BotOwnerName = usr.Name; packet.BotOwnerUserName =usr.Username; packet.BotNotificationId=notification.BotNotificationId; packet.Id=notification.Id; packet.NotificationButtons=notification.NotificationButtons; packet.OnClick=notification.OnClick; packet.Title =notification.Title; packet.BotUserString = notification.BotUserString; var ppacket=new ChatrWSMsg(); ppacket.SetPacketData(packet); Send(ppacket); } //packet.BotName=notification.SourceBotId } } public static class UserManagement { internal static Dictionary> Humans=new Dictionary>(); internal static Dictionary> Bots=new Dictionary>(); internal static HttpClient clt=new HttpClient(); internal static Dictionary _otaCodes=new Dictionary(); private static void SendHttpRequest(Dictionary dict) { //MET //HDR //URL //BDY Dictionary> headers=new Dictionary>(); string method="GET"; string url="http://example.com/"; byte[] body=new byte[0]; foreach(var d in dict) { if(d.Key == "MET") { method=d.Value; }else if(d.Key == "URL") { url = d.Value; }else if(d.Key == "BDY") { body = Convert.FromBase64String(d.Value); }else if(d.Key.StartsWith("HDR")) { string[] key= d.Key.Substring(3).Split(new char[]{':'},2); headers.Add(key[0],d.Value); } } HttpRequestMessage msg=new HttpRequestMessage(new HttpMethod(method),url); foreach(var h in headers) { msg.Headers.Add(h.Key,h.Value); } if(body.Length > 0) { msg.Content=new ByteArrayContent(body); } clt.SendAsync(msg).GetAwaiter().GetResult().Dispose(); } public static void HandleNotificationEventFirePacket(NotificationEventFirePacket packet) { if(DataBase.Notifications != null) { var p=DataBase.Notifications.FindOne(e=>e.BotUserString ==packet.BotUserString && e.BotNotificationId == packet.BotNotificationId); if(p != null) { if(string.IsNullOrWhiteSpace(packet.Button)) { //onclick switch(p.OnClick.Type) { case NotificationEventType.CallApiFromServer: SendHttpRequest(p.OnClick.Data); break; case NotificationEventType.SendCallbackToBot: SendNotificationEvent(packet); break; } }else{ try{ var p0 = p.NotificationButtons.Find(e=>{ return e.Text == packet.Button; }); if(p0==null) return; switch(p0.Event.Type) { case NotificationEventType.CallApiFromServer: SendHttpRequest(p0.Event.Data); break; case NotificationEventType.SendCallbackToBot: SendNotificationEvent(packet); break; } }catch(Exception ex) { _=ex; } } } } } public static bool DefaultVerificationStatus { get; set; } public static bool AllowLoginAsAnnonymous { get; set; } public static RegistrationResult RegisterAccount(string name,string username,string email,string password) { if(username.Equals("_anonymous") || email.Equals("anonymous@example.com")) { return new RegistrationResult("Can't Register Anonymous"); } if(IsValidPassword(password)) { var users=DataBase.Accounts; if(users != null){ var user =users.FindOne(e=>e.Username == username); if(user != null) { var res=new RegistrationResult("Username Exists"); return res; } user = users.FindOne(e=>e.Email == email); if(user != null) { var res=new RegistrationResult("Email Exists"); return res; } bool oobe=users.LongCount() == 0; Account a =new Account(); a.Username = username; a.SetPassword(password,true); a.Name = name; a.Email=email; a.Verified=UserManagement.DefaultVerificationStatus; a.IsAdmin = oobe; a.ShowUserNameToAnyBody=oobe; if(a.IsValid()) { users.Insert(a); if(oobe) { //Register Anonymous Account a2=new Account(); a2.IsAnonymous=true; a2.IsAdmin=false; a2.Verified=true; a2.Username="_anonymous"; a2.Email = "anonymous@example.com"; a2.ShowUserNameToAnyBody=true; a2.Name="Chatr Anonymous User"; a2.SetPassword("4209enabled",true); //dummy password would be 4209disabled when disabled users.Insert(a2); } return new RegistrationResult(a); } return new RegistrationResult("Invalid sign up details"); } return new RegistrationResult("Database Error: Accounts is null"); } return new RegistrationResult("Invalid Password"); } internal static void Logout(string session_id) { var sessions=DataBase.Sessions; if(!string.IsNullOrWhiteSpace(session_id) && sessions!=null) { var session=sessions.FindOne(e=>e.SessionId==session_id); if(session != null) { sessions.Delete(session.Id); } } } static Dictionary _opt=new Dictionary(); public static UserOptions GetUserOptions(Account account) { if(_opt.ContainsKey(account.Id)) { return _opt[account.Id]; } return new UserOptions(account); } public static void SetUserOptions(UserOptions options,ServerContext ctx) { options.Set(ctx); } public static AuthenticationResult Authenticate(string session_id) { var sessions=DataBase.Sessions; if(sessions == null) return new AuthenticationResult("Database Error: Sessions is null"); var users=DataBase.Accounts; if(users == null) return new AuthenticationResult("Database Error: Accounts is null"); foreach(var session in sessions.FindAll()) { if(session.SessionId.Equals(session_id) && DateTime.Now < session.Expires) { var user=users.FindById(session.UserId); if(user != null) { return new AuthenticationResult(user,session); } return new AuthenticationResult("User Removed"); } } return new AuthenticationResult("No valid session"); } public static string CreateAnotherSession(string session_id,DateTime expires) { var sessions=DataBase.Sessions; if(sessions == null) return null; var users=DataBase.Accounts; if(users == null) return null; var session=sessions.FindOne(e=>e.SessionId==session_id); if(session != null && DateTime.Now < session.Expires) { var user=users.FindById(session.UserId); if(user != null) { Session session2=new Session(); session2.Expires=expires; session2.RememberMe=true; session2.Created=DateTime.Now; session2.SessionId = Session.GetNewId(); session2.UserId=session.UserId; sessions.Insert(session2); return session2.SessionId; } } return null; } private static string CreateSession(Account user,DateTime expire,bool rememberMe) { var sessions=DataBase.Sessions; if(sessions == null) return null; string id= Session.GetNewId(); Session s=new Session(); s.Expires=expire; s.SessionId=id; s.UserId=user.Id; s.RememberMe=rememberMe; s.Created=DateTime.Now; sessions.Insert(s); return id; } public static Account GetAnonymous() { if(DataBase.Accounts != null) { var res=DataBase.Accounts.FindOne(e=>e.IsAnonymous); if(res!=null) return res; } return null; } public static LoginResult Login(string username,string password,bool rememberMe) { LoginResult res=new LoginResult(); res.Success=false; var users=DataBase.Accounts; if(users == null || username == "_anonymous" /*prevent logging in as lovely _anonymous account*/) return res; var user=users.FindOne(e=>e.Username == username); if(user != null && user.IsCorrectPassword(password)) { DateTime expire=rememberMe ? DateTime.Now.AddYears(1) : DateTime.Now.AddHours(2); res.Success=true; res.Account=user; res.Expires=expire; res.SessionId = CreateSession(user,expire,rememberMe); } return res; } public static string GetNameTextFromMessage(Message msg,bool fromMe) { if(!msg.IsFromBot && !msg.IsToBot) { //person to person if(msg.DestinationUserId == msg.SourceUserId) return "me"; if(DataBase.Accounts != null){ if(!fromMe) { //to me from username var user = DataBase.Accounts.FindById(msg.DestinationUserId); if(user != null) { return user.Name; } }else{ var user = DataBase.Accounts.FindById(msg.SourceUserId); if(user != null) { return user.Name; } } } }else{ if(DataBase.Bots != null) { if(msg.DestinationUserId == msg.SourceUserId) { //me-botname if(msg.IsFromBot ^ msg.IsToBot) { if(msg.IsFromBot) { //get bot for from var bot=DataBase.Bots.FindById(msg.SourceBotId); if(bot != null) return $"{bot.BotName} (My Bot)"; }else{ var bot=DataBase.Bots.FindById(msg.DestinationBotId); if(bot != null) return $"{bot.BotName} (My Bot)"; } } // bot to bot communication not supported in ui if at all }else{ if(DataBase.Accounts != null){ //the bot must not be yours if(msg.IsFromBot ^ !fromMe) { var a = DataBase.Accounts.FindById(msg.SourceUserId); var bot=DataBase.Bots.FindById(msg.SourceBotId); if(bot != null && a != null) return $"{bot.BotName} ({a.Name}'s Bot)"; //return $"{a.Username}-{bot.BotUserName}"; // {userName}-{botname} }else if(msg.IsToBot ^ fromMe) { var a = DataBase.Accounts.FindById(msg.DestinationUserId); var bot=DataBase.Bots.FindById(msg.DestinationBotId); if(bot != null && a != null) return $"{bot.BotName} ({a.Name}'s Bot)"; //return $"{a.Username}-{bot.BotUserName}"; } } } } } return ""; } public static string GetHashTextFromMessage(Message msg,bool fromMe) //true if you are ws to dest, false if loading my msg from data base { //from me = true //msg.Source will be considered me msg.Destination will be username //from me = false //msg.Destination will be considered username, destination will be me if(!msg.IsFromBot && !msg.IsToBot) { //person to person if(msg.DestinationUserId == msg.SourceUserId) return "me"; if(DataBase.Accounts != null){ if(!fromMe) { //to me from username var user = DataBase.Accounts.FindById(msg.DestinationUserId); if(user != null) { return user.Username; } }else{ var user = DataBase.Accounts.FindById(msg.SourceUserId); if(user != null) { return user.Username; } } } }else{ if(DataBase.Bots != null) { if(msg.DestinationUserId == msg.SourceUserId) { //me-botname if(msg.IsFromBot ^ msg.IsToBot) { if(msg.IsFromBot) { //get bot for from var bot=DataBase.Bots.FindById(msg.SourceBotId); if(bot != null) return $"me-{bot.BotUserName}"; }else{ var bot=DataBase.Bots.FindById(msg.DestinationBotId); if(bot != null) return $"me-{bot.BotUserName}"; } } // bot to bot communication not supported in ui if at all }else{ if(DataBase.Accounts != null){ //the bot must not be yours if(msg.IsFromBot ^ !fromMe) { var a = DataBase.Accounts.FindById(msg.SourceUserId); var bot=DataBase.Bots.FindById(msg.SourceBotId); if(bot != null && a != null) return $"{a.Username}-{bot.BotUserName}"; // {userName}-{botname} }else if(msg.IsToBot ^ fromMe) { var a = DataBase.Accounts.FindById(msg.DestinationUserId); var bot=DataBase.Bots.FindById(msg.DestinationBotId); if(bot != null && a != null) return $"{a.Username}-{bot.BotUserName}"; } } } } } return ""; } //this doesn't check whether message is legit, it is done somewhere else public static void SendMessage(Message msg) { msg.CreationTime=DateTime.Now; if(DataBase.Messages != null) { //put msg in database DataBase.Messages.Insert(msg); //easy as pie //send to user over ws, somewhat harder if(msg.IsToBot) { if(Bots.ContainsKey(msg.DestinationBotId)) { foreach(var bot in Bots[msg.DestinationBotId]) { bot.Push(msg); } } }else{ Account tmpAcc; if(DataBase.Accounts != null && ( tmpAcc = DataBase.Accounts.FindById(msg.DestinationUserId))!= null && tmpAcc.IsHidden(msg.SourceUserId,msg.IsFromBot ? msg.SourceBotId : -1) ) return;//impl hidden accounts and stuff if(Humans.ContainsKey(msg.DestinationUserId)) { foreach(var human in Humans[msg.DestinationUserId]) { human.Push(msg); } } } } } public static void SendNotification(Notification notification) { if(DataBase.Notifications != null) { if(Humans.ContainsKey(notification.DestinationUserId)) { foreach(var item in Humans[notification.DestinationUserId]) { item.Push(notification); } } } } public static void SendNotificationEvent(NotificationEventFirePacket notification) { if(DataBase.Notifications != null && !string.IsNullOrWhiteSpace(notification.BotUserString) && !string.IsNullOrWhiteSpace(notification.SourceUserName)) { var not=notification.BotUserString.Split(new char[]{'-'},2); if(not.Length < 2) return; string user=not[0]; string bot = not[1]; if(user == "me") { user = notification.SourceUserName; } long botId = GetBotId(user,bot); if(Bots.ContainsKey(botId)) { foreach(var item in Bots[botId]) { item.Push(notification); } } } } public static long GetUserId(string user) { Account a; if(DataBase.Accounts != null && (a=DataBase.Accounts.FindOne(e=>e.Username == user)) != null ) return a.Id; return -1; } public static long GetBotId(string user,string bot) { Bot b; if(DataBase.Bots != null && (b=DataBase.Bots.FindOne(e=>e.BotUserName == bot && e.UserId== GetUserId(user))) != null) return b.Id; return -1; } public static long GetBotId(long user,string bot) { Bot b; if(DataBase.Bots != null && (b=DataBase.Bots.FindOne(e=>e.BotUserName == bot && e.UserId== user)) != null) return b.Id; return -1; } public static IEnumerable GetMyBots(Account account,bool censored=true) { if(DataBase.Bots != null) { foreach(var bot in DataBase.Bots.Find(e=>e.UserId==account.Id)) { if(censored && account.IsHidden(account.Id,bot.Id)) continue; yield return bot; } } yield break; } public static IEnumerable GetBotsWithMe(Account account,Account other,bool censored=true) { if(censored && account.IsHidden(other.Id,-1)) yield break; List ids=new List(); if(DataBase.Messages != null && DataBase.Bots != null) { foreach(var msg in DataBase.Messages.FindAll()) { var e=msg; if(!((e.DestinationUserId == other.Id && e.SourceUserId ==account.Id && !e.IsFromBot && e.IsToBot ) ^ (e.DestinationUserId == account.Id && e.IsFromBot && !e.IsToBot && e.SourceUserId == other.Id) )) continue; if(msg.SourceUserId == account.Id) { if(!ids.Contains(msg.DestinationBotId)) ids.Add(msg.DestinationBotId); }else{ if(!ids.Contains(msg.SourceBotId)) ids.Add(msg.SourceBotId); } } foreach(var id in ids) { if( censored|| account.IsHidden(other.Id,id)) continue; var res=DataBase.Bots.FindById(id); if(res != null) yield return res; } } yield break; } public static IEnumerable GetUserWithMe(Account account,bool censored=true) { List ids=new List(); if(DataBase.Messages != null && DataBase.Accounts != null) { foreach(var msg in DataBase.Messages.FindAll()) { var e=msg; if(!(e.SourceUserId ==account.Id ^ e.DestinationUserId == account.Id )) continue; if(msg.SourceUserId == account.Id) { if(!ids.Contains(msg.DestinationUserId)) ids.Add(msg.DestinationUserId); }else{ if(!ids.Contains(msg.SourceUserId)) ids.Add(msg.SourceUserId); } } foreach(var usr in DataBase.Accounts.Find(e=>e.ShowUserNameToAnyBody==true)) { if(!ids.Contains(usr.Id)) { ids.Add(usr.Id); } } foreach(var id in ids) { if(censored && account.IsHidden(id,-1)) continue; var res=DataBase.Accounts.FindById(id); if(res != null) yield return res; } } yield break; } public static IEnumerable GetMessages(Account account,string user=null,string bot=null,bool censored=true) { if(DataBase.Messages != null) { if(string.IsNullOrWhiteSpace(user) && string.IsNullOrWhiteSpace(bot)) { //you foreach(var msg in DataBase.Messages.Find(e=> e.IsFromBot == false && e.IsToBot == false && e.SourceUserId == account.Id && e.DestinationUserId == account.Id)) { yield return msg; } } else if(string.IsNullOrWhiteSpace(bot) && !string.IsNullOrWhiteSpace(user)) { //a user var userId=GetUserId(user); if(censored && account.IsHidden(userId,-1)) yield break; foreach(var msg in DataBase.Messages.Find(e=>e.IsFromBot == false && e.IsToBot==false && ((e.SourceUserId == userId && e.DestinationUserId == account.Id) || (e.SourceUserId == account.Id && e.DestinationUserId == userId)))) { yield return msg; } }else if(!string.IsNullOrWhiteSpace(bot) && string.IsNullOrWhiteSpace(user)) { //my bots var botId = GetBotId(account.Id,bot); if(censored && account.IsHidden(account.Id,botId)) yield break; foreach(var msg in DataBase.Messages.Find(e=>( (e.SourceUserId == account.Id && e.IsFromBot==true && e.IsToBot==false && e.SourceBotId == botId && e.DestinationUserId ==account.Id) || (e.DestinationUserId == account.Id && e.IsToBot==true && e.IsFromBot == false && e.SourceUserId == account.Id) ))) { yield return msg; } } else if(!string.IsNullOrWhiteSpace(bot) && !string.IsNullOrWhiteSpace(user)){ // a bot var userId = GetUserId(user); var botId = GetBotId(userId,bot); if(account.IsHidden(userId,botId)) yield break; foreach(var msg in DataBase.Messages.Find(e=>( (e.SourceUserId == userId && e.IsFromBot==true && e.IsToBot==false && e.SourceBotId == botId && e.DestinationUserId == account.Id) || (e.DestinationUserId == userId && e.IsToBot==true && e.IsFromBot == false && e.SourceUserId == account.Id) ))) { yield return msg; } } } yield break; } public static AuthenticationBotResult AuthenticateApiKey(string apiKey) { if(DataBase.Bots == null)return new AuthenticationBotResult("Database Error: Bots is null"); //authenticate bot var bot=DataBase.Bots.FindOne(e=>e.ApiKey == apiKey); if(bot != null){ return new AuthenticationBotResult(bot); } return new AuthenticationBotResult("Bot Not found for apiKey"); } public static string GenerateApiKey(Account user,Bot bot) { if(DataBase.Bots == null)return null; string apiKey; do{ apiKey=Account.GetNewSalt(); } while(DataBase.Bots.FindOne(e=>e.ApiKey == apiKey) != null); bot.ApiKey=apiKey; bot.UserId=user.Id; DataBase.Bots.Insert(bot); return apiKey; } public static bool IsValidPassword(string password) { if(password.Length < 8) return false; //need a longer password if(password.StartsWith("password",StringComparison.OrdinalIgnoreCase)) return false; //prevents password password1 etc int num = 0; char lastChar='\0'; foreach(var c in password) //prevents 12345678 { if(c+1 == lastChar) {num++;} else if(c-1 == lastChar) {num++;} else {num=0;} lastChar=c; if(num > 5) return false; } return true; } internal static bool GetAuthCode(string key, out string session) { session=""; if(_otaCodes.ContainsKey(key)) { if(_otaCodes[key].Expires > DateTime.Now) { session=_otaCodes[key].SessionId; return true; } _otaCodes.Remove(key); } return false; } private static string GetRandOta() { string id=Session.GetNewId().Replace("=","ee").Replace("+","je").Replace("/","42"); return id; } internal static string CreateOTA(string sessionId) { string ota=GetRandOta(); while(_otaCodes.ContainsKey(ota)) { ota=GetRandOta(); } OTA o=new OTA(); o.Expires=DateTime.Now.AddMinutes(10); o.SessionId = sessionId; _otaCodes.Add(ota,o); return ota; } internal static void SendClearAll(ClearAllPacket pkt) { var uid= UserManagement.GetUserId(pkt.UserStr); if(Humans.ContainsKey(uid)) { foreach(var item in Humans[uid]) { item.Push(pkt); } } } } internal class OTA { public string SessionId {get;set;} public DateTime Expires {get;set;} } }