using PhilExampleCrawler.Common.Models; using PhilExampleCrawler.DataBase; using PhilExampleCrawler.DataBase.Models; namespace WebAPI { internal static class Transfrom { internal static User? ToCommon(this DB_User? dbUser) => dbUser == null ? null : new(dbUser.ID, dbUser.AuthCode, dbUser.Phone, dbUser.Optin_Telegram, dbUser.CreateDate) { HasTelegram = dbUser.HasTelegram, CrawlSessions = dbUser.CrawlSessions.Select(x => x.ToCommon()).ToList() }; internal static CrawlSession? ToCommon(this DB_CrawlSession? dbCS) => dbCS == null ? null : new(id: dbCS.ID, searchParams: new CrawlSearchParams(dbCS.Keywords, dbCS.LocationText, dbCS.CategoryID, dbCS.RadiusKM), minPrice: dbCS.MinPrice, maxPrice: dbCS.MaxPrice, isPrivate: dbCS.IsPrivate, isCommercial: dbCS.IsCommercial); internal static Insertion? ToCommon(this DB_Insertion? dbIns) => dbIns == null ? null : new Insertion(href: dbIns.Href, crawlSessionID: dbIns.CrawlSessionID, name: dbIns.Name, postCode: dbIns.PostCode, locationStr: dbIns.LocationStr, price: dbIns.Price, is_vb: dbIns.Is_VB, date: dbIns.Date, isTopAd: dbIns.IsTopAd, isHighlight: dbIns.IsHighlight, isRequest: dbIns.IsRequest); internal static DB_Insertion To_DB(this Insertion ins) { return new DB_Insertion(href: ins.Href, crawlSessionID: ins.CrawlSessionID, name: ins.Name, postCode: ins.PostCode, locationStr: ins.LocationStr, price: ins.Price, is_vb: ins.Is_VB, date: ins.Date, isTopAd: ins.IsTopAd, isHighlight: ins.IsHighlight, isRequest: ins.IsRequest); } internal static DB_CrawlSession ToDB(this CrawlSession cs, int userID) => new(cs.ID, userID, cs.SearchParams.KeyWords, cs.SearchParams.LocationStr, cs.SearchParams.CategoryID, cs.SearchParams.Radius, cs.MinPrice, cs.MaxPrice, cs.IsPrivate, cs.IsCommercial); } internal static class ThreadSafeCache { private static readonly List _userCache = new(); private static readonly object _userLock = new(); internal static async Task GetUserAsync(int userID) { User? user = null; lock (_userLock) user = _userCache.FirstOrDefault(u => u.ID == userID); //get from db and add to cache if (user == null) { UserAccess userDB = new(new DBSettings()); DB_User? dbUser = await userDB.GetUserAsync(userID); user = dbUser.ToCommon(); if (user != null) lock (_userLock) _userCache.Add(user); } return user; } internal static async Task AddUserAsync(string authCode, string phoneNumber, bool optin_telegram) { UserAccess userDB = new(new DBSettings()); DB_User? dbUser = await userDB.AddUserAsync(authCode, phoneNumber, optin_telegram); User? user = dbUser.ToCommon(); if (user != null) lock (_userLock) _userCache.Add(user); return user; } internal static async Task AddCrawlSessionAsync(int userID, CrawlSession cs) { CrawlSession? sess = null; User? user = await GetUserAsync(userID); if (user != null) { CrawlSessionAccess csDB = new(new DBSettings()); DB_CrawlSession? addedSess = await csDB.AddCrawlSessionAsync(cs.ToDB(userID)); sess = addedSess.ToCommon(); if (sess != null) lock (_userLock) user.CrawlSessions.Add(sess); } return sess; } internal static async Task UpdateCrawlSessionAsync(int userID, CrawlSession cs) { CrawlSessionAccess csDB = new(new DBSettings()); bool updated = await csDB.UpdateCrawlSessionAsync(cs.ToDB(userID)); if (updated) { //Replace in cache User? cachedUser = null; lock (_userLock) { cachedUser = _userCache.FirstOrDefault(u => u.CrawlSessions.Any(cs => cs.ID == cs.ID)); if (cachedUser != null) { int oldItemIndex = cachedUser.CrawlSessions.FindIndex(x => x.ID == cs.ID); if (oldItemIndex != -1) cachedUser.CrawlSessions[oldItemIndex] = cs; } } } return updated; } internal static async Task RemoveCrawlSessionAsync(int crawlSessionID) { CrawlSessionAccess csDB = new(new DBSettings()); bool deleted = await csDB.RemoveCrawlSessionAsync(crawlSessionID); if (deleted) { User? cachedUser = null; lock (_userLock) { cachedUser = _userCache.FirstOrDefault(u => u.CrawlSessions.Any(cs => cs.ID == crawlSessionID)); if (cachedUser != null) cachedUser.CrawlSessions.RemoveAll(cs => cs.ID == crawlSessionID); } } return deleted; } internal static async Task> AddInsertionsAsync(List insertions) { CrawlSessionAccess csDB = new(new()); List dbIns = await csDB.AddInsertionsAsync(insertions.Select(x => x.To_DB())); #pragma warning disable CS8619 // Nullability of reference types in value doesn't match target type. return dbIns.Select(x => x.ToCommon()).ToList(); #pragma warning restore CS8619 } internal static async Task> GetInsertions(int userID, int? limit) { CrawlSessionAccess csDB = new(new()); List dbIns = await csDB.GetInsertions(userID, limit); #pragma warning disable CS8619 // Nullability of reference types in value doesn't match target type. return dbIns.Select(x => x.ToCommon()).ToList(); #pragma warning restore CS8619 } } }