private async Task OnUserJoined(SocketGuildUser user) { Server server; if (!this.Client.Servers.ContainsKey(user.Guild.Id) || (server = this.Client.Servers[user.Guild.Id]) == null) { return; } bool verifiedByAge = false; IRole role = null; if (server.Config.VerifyRoleId > 0 && server.Config.VerifyAccountAgeDays > 0 && server.Config.VerifyAccountAge && Utils.GetTimeFromId(user.Id) + TimeSpan.FromDays(server.Config.VerifyAccountAgeDays) < DateTime.UtcNow && (role = server.Guild.GetRole(server.Config.VerifyRoleId)) != null) { verifiedByAge = true; try { await user.AddRoleAsync(role); } catch (HttpException e) { await server.HandleHttpException(e, "Failed to assign the verification role."); } catch (Exception e) { await HandleException(e, "Verification by account age", server.Id); } } if ((server.Config.CodeVerificationEnabled || server.Config.CaptchaVerificationEnabled) && server.Config.VerifyRoleId != 0 && server.Config.VerifyOnWelcome && !verifiedByAge) { await Task.Delay(3000); lock (this.DbLock) { ServerContext dbContext = ServerContext.Create(this.Client.DbConnectionString); UserData userData = dbContext.GetOrAddUser(server.Id, user.Id); PmErrorCode result = VerifyUsersPm(server, new List <UserData> { userData }).GetAwaiter().GetResult(); SocketTextChannel channel = null; if (server.Config.VerifyChannelId > 0 && (channel = server.Guild.GetTextChannel(server.Config.VerifyChannelId)) != null) { if (result == PmErrorCode.Failed) { channel.SendMessageSafe($"<@{user.Id}> I couldn't PM you, please re-enable PMs from server members and try again using the `{server.Config.CommandPrefix}verify` command.").GetAwaiter().GetResult(); } else if (result == PmErrorCode.Thrown500) { channel.SendMessageSafe($"<@{user.Id}> I couldn't PM you because Discord is currently pooping itself. " + Localisation.SystemStrings.DiscordShitEmoji).GetAwaiter().GetResult(); } } dbContext.Dispose(); } } }
public List <Command> Init(IValkyrjaClient iClient) { this.Client = iClient as ValkyrjaClient; List <Command> commands = new List <Command>(); this.Client.Events.UserJoined += OnUserJoined; this.Client.Events.MessageReceived += OnMessageReceived; // !unverify Command newCommand = new Command("unverify"); newCommand.Type = CommandType.Standard; newCommand.Description = "Remove verified status from someone."; newCommand.ManPage = new ManPage("<@user>", "`<@user>` - User mention of a user to have their verified status removed."); newCommand.RequiredPermissions = PermissionType.ServerOwner | PermissionType.Admin; newCommand.OnExecute += async e => { if (!e.Server.Config.CodeVerificationEnabled && !e.Server.Config.CaptchaVerificationEnabled) { await e.SendReplySafe("Verification is disabled on this server."); return; } string response = "Done."; ServerContext dbContext = ServerContext.Create(this.Client.DbConnectionString); List <UserData> mentionedUsers = this.Client.GetMentionedUsersData(dbContext, e); IRole role = e.Server.Guild.GetRole(e.Server.Config.VerifyRoleId); if (!mentionedUsers.Any() || role == null) { await e.SendReplySafe(UserNotFoundString); dbContext.Dispose(); return; } try { foreach (UserData userData in mentionedUsers) { userData.Verified = false; SocketGuildUser user = e.Server.Guild.GetUser(userData.UserId); if (user != null) { await user.RemoveRoleAsync(role); } } dbContext.SaveChanges(); } catch (Exception) { response = "Invalid configuration or permissions."; } dbContext.Dispose(); await e.SendReplySafe(response); }; commands.Add(newCommand); // !verify newCommand = new Command("verify"); newCommand.Type = CommandType.Standard; newCommand.Description = "This will send you (or someone else) some info about verification."; newCommand.ManPage = new ManPage("[@user [force]]", "`[@user]` - Optional user mention of someone else to send them the info.\n\n`[force]` - Optional administrative indicator that will directly verify mentioned user."); newCommand.OnExecute += async e => { if ((!e.Server.Config.CodeVerificationEnabled && !e.Server.Config.CaptchaVerificationEnabled) || e.Server.Config.VerifyRoleId == 0) { await e.SendReplySafe("Verification is disabled on this server."); return; } ServerContext dbContext = ServerContext.Create(this.Client.DbConnectionString); List <UserData> mentionedUsers = this.Client.GetMentionedUsersData(dbContext, e); string response = InvalidParametersString; PmErrorCode result = PmErrorCode.Undefined; // Admin verified someone. if (e.MessageArgs != null && e.MessageArgs.Length > 1 && e.Server.IsAdmin(e.Message.Author as SocketGuildUser) && e.MessageArgs[e.MessageArgs.Length - 1] == "force") { if (!mentionedUsers.Any()) { await e.SendReplySafe(UserNotFoundString); dbContext.Dispose(); return; } await VerifyUsers(e.Server, mentionedUsers); // actually verify people response = string.Format(VerifiedString, mentionedUsers.Select(u => u.UserId).ToMentions()); result = PmErrorCode.Undefined; } else if (string.IsNullOrEmpty(e.TrimmedMessage)) // Verify the author. { UserData userData = dbContext.GetOrAddUser(e.Server.Id, e.Message.Author.Id); result = await VerifyUsersPm(e.Server, new List <UserData> { userData }); if (result == PmErrorCode.Undefined) { response = AlreadyVerifiedString; } } else if (mentionedUsers.Any()) // Verify mentioned users. { result = await VerifyUsersPm(e.Server, mentionedUsers); if (result == PmErrorCode.Undefined) { response = AlreadyVerifiedString; } } switch (result) { case PmErrorCode.Success: response = SentString; break; case PmErrorCode.Failed: response = FailedPmString; break; case PmErrorCode.ThresholdExceeded: response = DidntPmString; break; case PmErrorCode.Thrown500: response = DiscordPoopString; break; case PmErrorCode.UserNull: response = UserNotFoundString; break; case PmErrorCode.Unknown: response = "Unknown error."; break; } if (mentionedUsers.Any()) { dbContext.SaveChanges(); } dbContext.Dispose(); await e.SendReplySafe(response); }; commands.Add(newCommand); return(commands); }
public async Task <PmErrorCode> VerifyUsersPm(Server server, List <UserData> users) { PmErrorCode pmErrorCode = PmErrorCode.Unknown; List <UserData> alreadyVerified = new List <UserData>(); List <UserData> nulls = new List <UserData>(); foreach (UserData userData in users) { IGuildUser user = server.Guild.GetUser(userData.UserId); if (user == null) { user = await this.Client.DiscordClient.Rest.GetGuildUserAsync(server.Id, userData.UserId); } if (user == null) { nulls.Add(userData); continue; } if (userData.Verified) { alreadyVerified.Add(userData); continue; } string verifyPm = ""; string value = ""; if (server.Config.CaptchaVerificationEnabled) { verifyPm = this.CaptchaPms[Utils.Random.Next(0, this.CaptchaPms.Length)]; value = "captcha"; } else { verifyPm = string.Format(PmCodeInfoString, server.Config.CommandPrefix); int source = Math.Abs((userData.UserId.ToString() + server.Id).GetHashCode()); int chunkNum = (int)Math.Ceiling(Math.Ceiling(Math.Log(source)) / 2); StringBuilder hashBuilder = new StringBuilder(chunkNum); for (int i = 0; i < chunkNum; i++) { char c = (char)((source % 100) / 4 + 97); hashBuilder.Append(c); source = source / 100; } string hash = hashBuilder.ToString(); hash = hash.Length > 5 ? hash.Substring(0, 5) : hash; string[] lines = server.Config.CodeVerifyMessage.Split('\n'); string[] words = null; bool found = false; bool theOtherHalf = false; try { for (int i = Utils.Random.Next(lines.Length / 2, lines.Length); !theOtherHalf || i >= lines.Length / 2; i--) { if (i <= lines.Length / 2) { if (theOtherHalf) { break; } theOtherHalf = true; i = lines.Length - 1; } if ((words = lines[i].Split(' ')).Length > 10) { int space = Math.Max(1, Utils.Random.Next(words.Length / 4, words.Length - 1)); lines[i] = lines[i].Insert(lines[i].IndexOf(words[space], StringComparison.Ordinal) - 1, $" the secret is: {hash} "); hashBuilder = new StringBuilder(); hashBuilder.AppendLine(verifyPm).AppendLine(""); for (int j = 0; j < lines.Length; j++) { hashBuilder.AppendLine(lines[j]); } verifyPm = hashBuilder.ToString(); value = hash; found = true; break; } } } catch (Exception e) { // This is ignored because user. Send them a message to fix it. found = false; await this.HandleException(e, "VerifyUserPm.hash", server.Id); } if (!found) { verifyPm = PmHashErrorString; } } if (!string.IsNullOrEmpty(value)) { ServerContext dbContext = ServerContext.Create(this.Client.DbConnectionString); VerificationData data = dbContext.Verification.AsQueryable().FirstOrDefault(u => u.ServerId == server.Id && u.UserId == userData.UserId); if (data == null) { data = new VerificationData() { ServerId = userData.ServerId, UserId = userData.UserId, Value = value }; dbContext.Verification.Add(data); } data.Value = value; dbContext.SaveChanges(); } string message = string.Format(PmString, user.Username, server.Guild.Name, verifyPm); if (server.Config.VerifyKarma > 0) { message += string.Format(PmKarmaString, server.Config.VerifyKarma, server.Config.CommandPrefix, server.Config.KarmaCurrency); } pmErrorCode = await this.Client.SendPmSafe(user, message); } if (alreadyVerified.Any()) { await VerifyUsers(server, alreadyVerified, false); pmErrorCode = PmErrorCode.Undefined; } if (nulls.Count == users.Count) { pmErrorCode = PmErrorCode.UserNull; } return(pmErrorCode); }