using NadekoBot.Services; using System; using NadekoBot.Services.Database.Models; using Discord; using NadekoBot.Modules.Xp.Common; using System.Linq; using Microsoft.EntityFrameworkCore; using System.Collections.Generic; namespace NadekoBot.Modules.Xp.Services { public class ClubService : INService { private readonly DbService _db; public ClubService(DbService db) { _db = db; } public bool CreateClub(IUser user, string clubName, out ClubInfo club) { //must be lvl 5 and must not be in a club already club = null; using (var uow = _db.UnitOfWork) { var du = uow.DiscordUsers.GetOrCreate(user); uow._context.SaveChanges(); var xp = new LevelStats(du.TotalXp); if (xp.Level >= 5 && du.Club == null) { du.IsClubAdmin = true; du.Club = new ClubInfo() { Name = clubName, Discrim = uow.Clubs.GetNextDiscrim(clubName), Owner = du, }; uow.Clubs.Add(du.Club); uow._context.SaveChanges(); } else return false; uow._context.Set() .RemoveRange(uow._context.Set().Where(x => x.UserId == du.Id)); club = du.Club; uow.Complete(); } return true; } public bool ToggleAdmin(IUser owner, IUser toAdmin) { bool newState; using (var uow = _db.UnitOfWork) { var club = uow.Clubs.GetByOwner(owner.Id); var adminUser = uow.DiscordUsers.GetOrCreate(toAdmin); if (club.OwnerId == adminUser.Id) return true; if (club == null || club.Owner.UserId != owner.Id || !club.Users.Contains(adminUser)) throw new InvalidOperationException(); newState = adminUser.IsClubAdmin = !adminUser.IsClubAdmin; uow.Complete(); } return newState; } public ClubInfo GetClubByMember(IUser user) { using (var uow = _db.UnitOfWork) { return uow.Clubs.GetByMember(user.Id); } } public bool SetClubIcon(ulong ownerUserId, string url) { using (var uow = _db.UnitOfWork) { var club = uow.Clubs.GetByOwner(ownerUserId, set => set); if (club == null) return false; club.ImageUrl = url; uow.Complete(); } return true; } public bool GetClubByName(string clubName, out ClubInfo club) { club = null; var arr = clubName.Split('#'); if (arr.Length < 2 || !int.TryParse(arr[arr.Length - 1], out var discrim)) return false; //incase club has # in it var name = string.Concat(arr.Except(new[] { arr[arr.Length - 1] })); if (string.IsNullOrWhiteSpace(name)) return false; using (var uow = _db.UnitOfWork) { club = uow.Clubs.GetByName(name, discrim); if (club == null) return false; else return true; } } public bool ApplyToClub(IUser user, ClubInfo club) { using (var uow = _db.UnitOfWork) { var du = uow.DiscordUsers.GetOrCreate(user); uow._context.SaveChanges(); if (du.Club != null || new LevelStats(du.TotalXp).Level < club.MinimumLevelReq || club.Bans.Any(x => x.UserId == du.Id) || club.Applicants.Any(x => x.UserId == du.Id)) { //user banned or a member of a club, or already applied, // or doesn't min minumum level requirement, can't apply return false; } var app = new ClubApplicants { ClubId = club.Id, UserId = du.Id, }; uow._context.Set().Add(app); uow.Complete(); } return true; } public bool AcceptApplication(ulong clubOwnerUserId, string userName, out DiscordUser discordUser) { discordUser = null; using (var uow = _db.UnitOfWork) { var club = uow.Clubs.GetByOwnerOrAdmin(clubOwnerUserId); if (club == null) return false; var applicant = club.Applicants.FirstOrDefault(x => x.User.ToString().ToLowerInvariant() == userName.ToLowerInvariant()); if (applicant == null) return false; applicant.User.Club = club; applicant.User.IsClubAdmin = false; club.Applicants.Remove(applicant); //remove that user's all other applications uow._context.Set() .RemoveRange(uow._context.Set().Where(x => x.UserId == applicant.User.Id)); discordUser = applicant.User; uow.Complete(); } return true; } public ClubInfo GetClubWithBansAndApplications(ulong ownerUserId) { using (var uow = _db.UnitOfWork) { return uow.Clubs.GetByOwnerOrAdmin(ownerUserId); } } public bool LeaveClub(IUser user) { using (var uow = _db.UnitOfWork) { var du = uow.DiscordUsers.GetOrCreate(user); if (du.Club == null || du.Club.OwnerId == du.Id) return false; du.Club = null; du.IsClubAdmin = false; uow.Complete(); } return true; } public bool ChangeClubLevelReq(ulong userId, int level) { if (level < 5) return false; using (var uow = _db.UnitOfWork) { var club = uow.Clubs.GetByOwner(userId); if (club == null) return false; club.MinimumLevelReq = level; uow.Complete(); } return true; } public bool Disband(ulong userId, out ClubInfo club) { using (var uow = _db.UnitOfWork) { club = uow.Clubs.GetByOwner(userId); if (club == null) return false; uow.Clubs.Remove(club); uow.Complete(); } return true; } public bool Ban(ulong ownerUserId, string userName, out ClubInfo club) { using (var uow = _db.UnitOfWork) { club = uow.Clubs.GetByOwnerOrAdmin(ownerUserId); if (club == null) return false; var usr = club.Users.FirstOrDefault(x => x.ToString().ToLowerInvariant() == userName.ToLowerInvariant()) ?? club.Applicants.FirstOrDefault(x => x.User.ToString().ToLowerInvariant() == userName.ToLowerInvariant())?.User; if (usr == null) return false; if (club.OwnerId == usr.Id) // can't ban the owner kek, whew return false; club.Bans.Add(new ClubBans { Club = club, User = usr, }); club.Users.Remove(usr); var app = club.Applicants.FirstOrDefault(x => x.UserId == usr.Id); if (app != null) club.Applicants.Remove(app); uow.Complete(); } return true; } public bool UnBan(ulong ownerUserId, string userName, out ClubInfo club) { using (var uow = _db.UnitOfWork) { club = uow.Clubs.GetByOwnerOrAdmin(ownerUserId); if (club == null) return false; var ban = club.Bans.FirstOrDefault(x => x.User.ToString().ToLowerInvariant() == userName.ToLowerInvariant()); if (ban == null) return false; club.Bans.Remove(ban); uow.Complete(); } return true; } public bool Kick(ulong ownerUserId, string userName, out ClubInfo club) { using (var uow = _db.UnitOfWork) { club = uow.Clubs.GetByOwnerOrAdmin(ownerUserId); if (club == null) return false; var usr = club.Users.FirstOrDefault(x => x.ToString().ToLowerInvariant() == userName.ToLowerInvariant()); if (usr == null) return false; if (club.OwnerId == usr.Id) return false; club.Users.Remove(usr); var app = club.Applicants.FirstOrDefault(x => x.UserId == usr.Id); if (app != null) club.Applicants.Remove(app); uow.Complete(); } return true; } public ClubInfo[] GetClubLeaderboardPage(int page) { if (page < 0) throw new ArgumentOutOfRangeException(nameof(page)); using (var uow = _db.UnitOfWork) { return uow.Clubs.GetClubLeaderboardPage(page); } } } }