public async Task BecomeGodfather(IUser actor, IUserShim targetShim) { var target = await targetShim.Load(); using (var context = await ContextProvider.Connect()) using (var transact = context.Database.BeginTransaction(IsolationLevel.Serializable)) { var godfather = await context.Users.Include(u => u.Membership).SingleAsync(u => u.Id == actor.UserId); // if godfather is not a real member, this method call was super duper obsolete if (godfather.Membership == null) { return; } var guest = await context.Users.Include(u => u.Membership).Include(u => u.GuestInvite) .Include(u => u.PersistentGuest.Godfathers).SingleAsync(u => u.Id == target.UserId); if (guest.PersistentGuest == null) { // only guests can be promoted to persistentguests if (guest.GuestInvite == null) { return; } guest.PersistentGuest = new PersistentGuest { OriginalInvite = guest.GuestInvite, }; guest.GuestInvite = null; CertificateCredentials creds; if (Fancyauth.GuestCredentials.TryGetValue(target.UserId, out creds)) { guest.CertCredentials.Add(creds); } else { await actor.SendMessage("No certificate found."); return; } } // ignore the nop case if (guest.PersistentGuest.Godfathers.Contains(godfather.Membership)) { return; } guest.PersistentGuest.Godfathers.Add(godfather.Membership); await context.SaveChangesAsync(); transact.Commit(); } await target.SendMessage("Irgendwann - möglicherweise aber auch nie - werde ich dich bitten, mir eine kleine Gefälligkeit zu erweisen."); }
public async Task Integrate(IUser actor, IUserShim targetShim) { var target = await targetShim.Load(); using (var context = await ContextProvider.Connect()) using (var transact = context.Database.BeginTransaction(IsolationLevel.Serializable)) { var targetEntity = await context.Users.Include(x => x.Membership).Include(x => x.PersistentGuest) .Include(x => x.GuestInvite).SingleAsync(x => x.Id == target.UserId); var actorEntity = await context.Users.Include(x => x.Membership).Include(x => x.PersistentGuest) .Include(x => x.GuestInvite).Include(x => x.CertCredentials) .SingleAsync(x => x.Id == actor.UserId); // reqiurements: // * a member // * targets a non-member // * specifically, a non-persistent guest if ((targetEntity.Membership != null) || (targetEntity.PersistentGuest != null) || (actorEntity.Membership == null)) { await actor.SendMessage("Integration denied."); return; } CertificateCredentials creds; if (Fancyauth.GuestCredentials.TryGetValue(target.UserId, out creds)) { actorEntity.CertCredentials.Add(creds); } else { await actor.SendMessage("No certificate found."); return; } await context.SaveChangesAsync(); transact.Commit(); } await targetShim.Kick("You have been integrated into " + actor.Name); }
public async Task RudeUser(IUser actor, IUserShim targetShim) { var bytes = new byte[4]; SecureRng.GetBytes(bytes); int seed = BitConverter.ToInt32(bytes, 0); var rng = new Random(seed); var target = await targetShim.Load(); // TODO: Remove this check when guests have UserIds if (target.UserId <= 0 || actor.UserId <= 0) { return; } var rudeEntity = new RudeEntity { Id = -1, ActorId = actor.UserId, TargetId = target.UserId, ActualTargetId = null, Timestamp = DateTimeOffset.Now, }; int targetInRudes; // if the actor ruded himself, he won't be kicked bool kick = false; lock (Rudes) { var oneYear = DateTimeOffset.Now.AddYears(-1); var actorOutRudeQuery = Rudes // get all rudes which actor has done .Where(r => r.ActorId == actor.UserId) // and where he didn't rude himself by ruding too often .Where(r => r.ActualTargetId == null); // if actor rudes himself or has already ruded in last Minute bool punishActor = actorOutRudeQuery // take all rudes, where the actor hasn't kicked someone // (kicking by ruding does not have a cooldown) .Where(r => r.Duration != null) // test, if the actor has ruded anyone in last minute .Any(r => r.Timestamp > DateTime.Now.AddMinutes(-1)); // if actor already ruded in last minute, he will be ruded instead of target if (punishActor) { rudeEntity.ActualTargetId = rudeEntity.TargetId; rudeEntity.TargetId = actor.UserId; // he will be the new target target = actor; } // get active rudes on target and add current rude targetInRudes = GetActiveInRudes(target.UserId).Count() + 1; if (targetInRudes > PREFIXES.Length && !punishActor) { kick = true; rudeEntity.Duration = null; } else { var actorOutRudes = actorOutRudeQuery.Count(); var medianQuery = from r in Rudes where r.Timestamp > oneYear group Math.Log((r.Timestamp - oneYear).TotalMinutes) by r.ActorId into g select g.Sum(); var median = medianQuery.Median(); double durationFactor = actorOutRudes == 0 ? 2 : median.Value / actorOutRudes; durationFactor = Math.Max(durationFactor, 0.25); durationFactor = Math.Min(durationFactor, 2); durationFactor *= rng.NextDouble() * targetInRudes; var duration = TimeSpan.FromHours(durationFactor * 2).Ticks; rudeEntity.Duration = TimeSpan.FromTicks(Math.Min(duration, TimeSpan.FromDays(1).Ticks)); } // add rude Rudes.Add(rudeEntity); } if (kick) { await target.Kick(REASONS[rng.Next(REASONS.Length)]); } else { target.Name = GetUsername(target.Name, targetInRudes, GetReudigLevel(target.UserId)); await target.SaveChanges(); } await actor.SendMessage("Ruded with: " + rudeEntity.Duration); }