コード例 #1
0
            public async Task IsCommand(string person)
            {
                //SocketGuildUser discordUser = null;

                SocketGuildUser discordUser = Context.Guild.Users.FirstOrDefault(item => (item.Nickname == null) ? item.Username.ToLower().Contains(person.ToLower()) : item.Nickname.ToLower().Contains(person.ToLower()));



                //if(discordUser == null)
                //{
                //	discordUser = Context.Guild.Users.FirstOrDefault(item => item.Username.Equals(person, StringComparison.OrdinalIgnoreCase));
                //}
                //TownUser user = Database.Users.FindOne(item => item.Name == person);

                TownUser user = Database.Users.FindById(discordUser.Id);

                if (user == null)
                {
                    Random random = new Random();

                    await ReplyAsync(string.Format(UnknownReplies[random.Next(UnknownReplies.Length)], (discordUser.Nickname == null) ? discordUser.Username : discordUser.Nickname, Context.User.Mention));

                    return;
                }

                if (user.Description == null)
                {
                    await ReplyAsync("I've met them, they didn't tell me much about themselves though.");

                    return;
                }

                await ReplyAsync((discordUser.Nickname == null)?discordUser.Username + " is " + user.Description : discordUser.Nickname + " is " + user.Description);
            }
コード例 #2
0
        public async Task Link(IUser user, int altaId)
        {
            TownUser entry = Database.GetUser(user);

            await Link(user, entry, altaId);

            await ReplyAsync("Done!");
        }
コード例 #3
0
        async Task Link(IUser discordUser, TownUser user, int id)
        {
            if (user.AltaInfo == null)
            {
                user.AltaInfo = new UserAltaInfo();
            }

            if (user.AltaInfo.Identifier == id)
            {
                await ReplyAsync(discordUser.Mention + ", " + "Already connected!");

                await Context.Message.DeleteAsync();

                await AccountService.UpdateAsync(user, (SocketGuildUser)discordUser);

                return;
            }

            if (user.AltaInfo.Identifier != 0)
            {
                await ReplyAsync(discordUser.Mention + ", " + $"Unlinking your Discord from {user.AltaInfo.Username}...");

                await Context.Message.DeleteAsync();

                user.AltaInfo.Unlink();

                Database.Users.Update(user);
            }

            if (Database.Users.Exists(x => x.AltaInfo != null && x.AltaInfo.Identifier == id && x.UserId != discordUser.Id))
            {
                var oldUsers = Database.Users.Find(x => x.AltaInfo.Identifier == id && x.UserId != discordUser.Id);

                foreach (var x in oldUsers)
                {
                    var olddiscorduser = Context.Client.GetUser(x.UserId);

                    await ReplyAsync(discordUser.Mention + ", " + $"Unlinking your Alta account from {olddiscorduser.Mention}...");

                    await Context.Message.DeleteAsync();

                    x.AltaInfo.Unlink();

                    Database.Users.Update(x);
                }
            }

            user.AltaInfo.Identifier = id;

            Database.Users.Update(user);

            await ReplyAsync(Context.User.Mention + ", " + $"Successfully linked to your Alta account! Hey there {user.AltaInfo.Username}!");

            await Context.Message.DeleteAsync();

            await AccountService.UpdateAsync(user, (SocketGuildUser)discordUser);
        }
コード例 #4
0
        void FixUser(TownUser user)
        {
            if (user.AltaInfo != null)
            {
                user.AltaId = user.AltaInfo.Identifier;

                user.SupporterExpiry = user.AltaInfo.SupporterExpiry;

                user.SupporterExpiryDay = user.SupporterExpiry?.Date;
            }
        }
コード例 #5
0
        public async Task WhoReverse(IUser user)
        {
            TownUser entry = Database.GetUser(user);

            if (entry.AltaInfo != null)
            {
                await ReplyAsync(entry.Name + " is " + entry.AltaInfo.Username);
            }
            else
            {
                await ReplyAsync(entry.Name + " hasnt linked their alta account");
            }
        }
コード例 #6
0
        public async Task IsLinked()
        {
            TownUser user = Database.GetUser(Context.User);

            if (user.AltaInfo == null || user.AltaInfo.Identifier == 0)
            {
                await ReplyAsync(Context.User.Mention + ", " + "You have not linked to an Alta account! To link, visit the 'Account Settings' page in the launcher.");
            }
            else
            {
                await ReplyAsync(Context.User.Mention + ", " + $"Your account is currently linkedto " + user.AltaInfo.Username + "!");
            }
        }
コード例 #7
0
        public async Task Who(string username)
        {
            TownUser entry = Database.Users.FindOne(item => item.AltaInfo != null && string.Compare(item.AltaInfo.Username, username, true) == 0);

            if (entry != null)
            {
                await ReplyAsync(username + " is " + entry.Name);
            }
            else
            {
                await ReplyAsync("Couldn't find " + username);
            }
        }
コード例 #8
0
        public async Task UserList()
        {
            if (Context.Guild == null)
            {
                return;
            }

            if (!(Context.User as IGuildUser).RoleIds.Contains <ulong>(334935631149137920))
            {
                return;
            }

            await ReplyAsync("Starting...");

            StringBuilder result = new StringBuilder();

            result
            .Append("ID")
            .Append(',')
            .Append("Username")
            .Append(',')
            .Append("Nickname")
            .Append(',')
            .Append("Joined")
            .Append(',')
            .Append("Last Message")
            .Append(',')
            .Append("Score")
            .Append('\n');

            foreach (IGuildUser user in (Context.Guild as SocketGuild).Users)
            {
                TownUser townUser = Database.GetUser(user);

                result
                .Append(user.Id)
                .Append(',')
                .Append(user.Username.Replace(',', '_'))
                .Append(',')
                .Append(user.Nickname?.Replace(',', '_'))
                .Append(',')
                .Append(townUser.InitialJoin.ToString("dd-MM-yy"))
                .Append(',')
                .Append(townUser.Scoring?.LastMessage.ToString("dd-MM-yy"))
                .Append('\n');
            }

            System.IO.File.WriteAllText("D:/Output/Join Dates.txt", result.ToString());

            await ReplyAsync("I'm done now :)");
        }
コード例 #9
0
        public async Task ListExtra()
        {
            foreach (SocketGuildUser user in Context.Guild.GetRole(547202953505800233).Members)
            {
                TownUser entry = Database.GetUser(user);

                if (entry.AltaInfo == null || !entry.AltaInfo.IsSupporter)
                {
                    await ReplyAsync(user.Username + " " + (entry.AltaInfo == null));
                }
            }

            await ReplyAsync("Done!");
        }
コード例 #10
0
        public async Task Set([Remainder] string description)
        {
            if (description.Length > 120)
            {
                await ReplyAsync("Limit of 120 characters");

                return;
            }

            TownUser user = Database.GetUser(Context.User);

            user.Description = description;

            Database.Users.Update(user);
        }
コード例 #11
0
        public async Task PlayTime2(IUser userArg)
        {
            TownUser user = Database.GetUser(userArg);

            if (user == null || user.AltaInfo == null || user.AltaInfo.Identifier == 0)
            {
                await ReplyAsync(Context.User.Mention + ", " + "You have not linked to an Alta account! To link, visit the 'Account Settings' page in the launcher.");
            }
            else
            {
                var stats = await AltaAPI.ApiClient.UserClient.GetUserStatisticsAsync(user.AltaInfo.Identifier);

                await ReplyAsync("Play time: " + stats.PlayTime.TotalHours.ToString("0.00") + " hours");
            }
        }
コード例 #12
0
        public async Task GetTalems()
        {
            TownUser user = Database.GetUser(Context.User);

            if (user.AltaInfo == null || user.AltaInfo.Identifier == 0)
            {
                await ReplyAsync("You have not linked your alta account. Go to the launcher to link your account");
            }
            else
            {
                var account = await AltaApi.ApiClient.ShopClient.Account.GetShopAccountInfo();

                await ReplyAsync($"You have {account.ShardBalance} Talems");
            }
        }
コード例 #13
0
        public async Task Update(SocketUser user)
        {
            TownUser entry = Database.GetUser(user);

            if (entry.AltaInfo != null)
            {
                await AccountService.UpdateAsync(entry, (SocketGuildUser)user);

                await ReplyAsync(Context.User.Mention + ", " + $"{entry.AltaInfo.Username}'s account info has been updated!");
            }
            else
            {
                await ReplyAsync(Context.User.Mention + ", " + user.Username + " have not linked to an Alta account!");
            }
        }
コード例 #14
0
        public async Task Who(string username)
        {
            var userId = await AltaApi.ApiClient.UserClient.GetUserInfoAsync(username);

            TownUser entry = Database.Users.FindByIndex(userId.Identifier, "alta_id-index", "AltaId");

            if (entry != null)
            {
                await ReplyAsync(username + " is " + entry.Name);
            }
            else
            {
                await ReplyAsync("Couldn't find " + username);
            }
        }
コード例 #15
0
        public async Task Update()
        {
            TownUser entry = Database.GetUser(Context.User);

            if (entry.AltaInfo != null)
            {
                await AccountService.UpdateAsync(entry, (SocketGuildUser)Context.User);

                await ReplyAsync(Context.User.Mention + ", " + $"Hey {entry.AltaInfo.Username}, your account info has been updated!");
            }
            else
            {
                await ReplyAsync(Context.User.Mention + ", " + "You have not linked to an Alta account! To link, visit the 'Account Settings' page in the launcher.");
            }
        }
コード例 #16
0
        public async Task AccountInfoFull()
        {
            TownUser user = Database.GetUser(Context.User);

            if (user.AltaInfo == null || user.AltaInfo.Identifier == 0)
            {
                await ReplyAsync("You have not linked your alta account. Go to the launcher to link your account");
            }
            else
            {
                var account = await AltaApi.ApiClient.ShopClient.Account.GetShopAccountInfo(user.AltaInfo.Identifier);

                var stats = await AltaApi.ApiClient.UserClient.GetUserStatisticsAsync(user.AltaInfo.Identifier);

                await ReplyAsync($"In Game Username: {user.AltaInfo.Username}\nTalems: {account.ShardBalance}\nSupporter: {account.MemberStatus.IsSupporter}\nSupporter End: {account.MemberStatus.MemberEndDate}\nPlay Time: {stats.PlayTime.TotalHours:0.0} hours\nCreated Account: {stats.SignupTime.ToShortDateString()} ({(DateTime.UtcNow - stats.SignupTime).TotalDays:0} days ago) ");
            }
        }
コード例 #17
0
		Task Handle(SocketMessage message)
		{
			TownUser user = database.GetUser(message.Author);

			if (user.Scoring == null)
			{
				user.Scoring = new UserScoring();
			}

			UserScoring scoring = user.Scoring;

			DateTime now = DateTime.UtcNow;

			if ((now - scoring.LastMessage).TotalMinutes > 1)
			{
				if (scoring.UsedHourPoints > 0)
				{
					if ((now - scoring.UsedFirstHourPoint).TotalHours > 1)
					{
						scoring.UsedHourPoints = 0;
					}
				}

				if (scoring.UsedHourPoints < 20)
				{
					if (scoring.UsedHourPoints == 0)
					{
						scoring.UsedFirstHourPoint = now;
					}

					scoring.UsedHourPoints++;

					scoring.Score += 10;

					scoring.LastMessage = now;
				}
			}

			return Task.CompletedTask;
		}
コード例 #18
0
        public TownUser GetUser(IUser user)
        {
            TownUser result = Users.FindOne(x => x.UserId == user.Id);

            if (result == null)
            {
                result = new TownUser()
                {
                    UserId = user.Id, Name = user.Username
                };

                Users.Insert(result);
            }
            else if (result.Name != user.Username)
            {
                result.Name = user.Username;

                Users.Update(result);
            }

            return(result);
        }
コード例 #19
0
            public async Task IsCommand(string person)
            {
                TownUser user = Database.Users.FindOne(item => item.Name == person);

                if (user == null)
                {
                    Random random = new Random();

                    await ReplyAsync(string.Format(UnknownReplies[random.Next(UnknownReplies.Length)], person, Context.User.Mention));

                    return;
                }

                if (user.Description == null)
                {
                    await ReplyAsync("I've met them, they didn't tell me much about themselves though.");

                    return;
                }

                await ReplyAsync(person + " is " + user.Description);
            }
コード例 #20
0
        public TownUser GetUser(IUser user)
        {
            TownUser result = Users.FindOne(x => x.UserId == user.Id);

            bool isChanged = false;

            if (result == null)
            {
                result = new TownUser()
                {
                    UserId = user.Id, Name = user.Username
                };

                Users.Insert(result);
            }
            else if (result.Name != user.Username)
            {
                result.Name = user.Username;

                isChanged = true;
            }

            if (result.InitialJoin == default(DateTime) && user is IGuildUser guildUser && guildUser.JoinedAt.HasValue)
            {
                result.InitialJoin = guildUser.JoinedAt.Value.UtcDateTime;

                isChanged = true;
            }

            if (isChanged)
            {
                Users.Update(result);
            }

            return(result);
        }
コード例 #21
0
		void Migrate()
		{
			string target = "AltaLink.txt";

			FileInfo fileInfo = new FileInfo($"./{target}");

			if (!fileInfo.Exists)
			{
				Console.WriteLine("Can't find AltaLinks");
				return;
			}

			Console.WriteLine("Migrating with AltaLinks");



			using (StreamReader reader = new StreamReader($"./{target}"))
			{
				while (!reader.EndOfStream)
				{
					string line = reader.ReadLine().Trim();
					
					string[] split = line.Split(' ');
					
					if (split.Length == 3)
					{
						ulong discord = ulong.Parse(split[0]);
						string name = split[1];

						if (!int.TryParse(split[2], out int id))
						{
							Console.WriteLine("Failed to parse id for " + line);
							continue;
						}

						TownUser user = Database.Users.FindOne(item => item.UserId == discord);
						
						if (user == null)
						{
							Console.WriteLine("Couldn't find user " + discord + " for " + name);
							continue;
						}

						if (user.AltaInfo != null)
						{
							//Console.WriteLine("Already processed " + line);
							continue;
						}

						Console.WriteLine("Connecting " + user.Name + " to " + name);

						user.AltaInfo = new UserAltaInfo()
						{
							Identifier = id,
							Username = name
						};

						Database.Users.Update(user);

						UpdateAsync(user, null).Wait();
					}
					else
					{
						Console.WriteLine("Length not 3 " + line);
					}
				}
			}
		}
コード例 #22
0
        public async Task Verify([Remainder] string encoded)
        {
            JwtSecurityToken token;
            Claim            userData;
            Claim            altaId;

            TownUser user = Database.GetUser(Context.User);

            try
            {
                token = new JwtSecurityToken(encoded);

                userData = token.Claims.FirstOrDefault(item => item.Type == "user_data");
                altaId   = token.Claims.FirstOrDefault(item => item.Type == "UserId");
            }
            catch
            {
                await ReplyAsync(Context.User.Mention + ", " + "Invalid verification token.");

                await Context.Message.DeleteAsync();

                return;
            }

            if (userData == null || altaId == null)
            {
                await ReplyAsync(Context.User.Mention + ", " + "Invalid verification token.");

                await Context.Message.DeleteAsync();
            }
            else
            {
                try
                {
                    VerifyData result = JsonConvert.DeserializeObject <VerifyData>(userData.Value);

                    string test      = result.discord.ToLower();
                    string expected  = Context.User.Username.ToLower() + "#" + Context.User.Discriminator;
                    string alternate = Context.User.Username.ToLower() + " #" + Context.User.Discriminator;


                    if (test != expected.ToLower() && test != alternate.ToLower())
                    {
                        await ReplyAsync(Context.User.Mention + ", " + "Make sure you correctly entered your account info! You entered: " + result.discord + ". Expected: " + expected);

                        await Context.Message.DeleteAsync();

                        return;
                    }

                    int id = int.Parse(altaId.Value);

                    bool isValid = await AltaApi.ApiClient.ServicesClient.IsValidShortLivedIdentityTokenAsync(token);

                    if (isValid)
                    {
                        await Link(Context.User, user, id);

                        if (user.AltaInfo.Identifier == id)
                        {
                            await ReplyAsync(Context.User.Mention + ", " + "Already connected!");

                            await Context.Message.DeleteAsync();

                            await AccountService.UpdateAsync(user, (SocketGuildUser)Context.User);

                            return;
                        }

                        if (user.AltaInfo.Identifier != 0)
                        {
                            await ReplyAsync(Context.User.Mention + ", " + $"Unlinking your Discord from {user.AltaInfo.Username}...");

                            await Context.Message.DeleteAsync();

                            user.AltaInfo.Unlink();
                        }

                        if (Database.Users.Exists(x => x.AltaInfo != null && x.AltaInfo.Identifier == id && x.UserId != Context.User.Id))
                        {
                            var oldUsers = Database.Users.Find(x => x.AltaInfo.Identifier == id && x.UserId != Context.User.Id);

                            foreach (var x in oldUsers)
                            {
                                var olddiscorduser = Context.Client.GetUser(x.UserId);

                                await ReplyAsync(Context.User.Mention + ", " + $"Unlinking your Alta account from {olddiscorduser.Mention}...");

                                await Context.Message.DeleteAsync();

                                x.AltaInfo.Unlink();
                            }
                        }

                        user.AltaInfo.Identifier = id;

                        await AccountService.UpdateAsync(user, (SocketGuildUser)Context.User);

                        await ReplyAsync(Context.User.Mention + ", " + $"Successfully linked to your Alta account! Hey there {user.AltaInfo.Username}!");

                        await Context.Message.DeleteAsync();
                    }
                    else
                    {
                        await ReplyAsync(Context.User.Mention + ", " + "Invalid token! Try creating a new one!");

                        await Context.Message.DeleteAsync();
                    }
                }
                catch (Exception e)
                {
                    await ReplyAsync(Context.User.Mention + ", " + "Invalid verification token : " + e.Message);
                }
            }
        }
コード例 #23
0
        public async Task AmI()
        {
            TownUser user = Database.GetUser(Context.User);

            await ReplyAsync(user.Name + " is " + (user.Description ?? "... You?"));
        }
コード例 #24
0
        public async Task Joined()
        {
            TownUser user = Database.GetUser(Context.User);

            await ReplyAsync($"{Context.User.Mention} joined on {user.InitialJoin.ToString("dd/MMM/yyyy")}");
        }
コード例 #25
0
        public async Task Verify([Remainder] string encoded)
        {
            JwtSecurityToken token;
            Claim            userData;
            Claim            altaId;

            TownUser user = Database.GetUser(Context.User);

            try
            {
                token = new JwtSecurityToken(encoded);

                userData = token.Claims.FirstOrDefault(item => item.Type == "user_data");
                altaId   = token.Claims.FirstOrDefault(item => item.Type == "UserId");
            }
            catch
            {
                await ReplyAsync(Context.User.Mention + ", " + "Invalid verification token.");

                await Context.Message.DeleteAsync();

                return;
            }

            if (userData == null || altaId == null)
            {
                await ReplyAsync(Context.User.Mention + ", " + "Invalid verification token.");

                await Context.Message.DeleteAsync();
            }
            else
            {
                try
                {
                    VerifyData result = JsonConvert.DeserializeObject <VerifyData>(userData.Value);

                    string test      = result.discord.ToLower();
                    string expected  = Context.User.Username.ToLower() + "#" + Context.User.Discriminator;
                    string alternate = Context.User.Username.ToLower() + " #" + Context.User.Discriminator;


                    if (test != expected.ToLower() && test != alternate.ToLower())
                    {
                        await ReplyAsync(Context.User.Mention + ", " + "Make sure you correctly entered your account info! You entered: " + result.discord + ". Expected: " + expected);

                        await Context.Message.DeleteAsync();

                        return;
                    }

                    int id = int.Parse(altaId.Value);

                    bool isValid = await AltaApi.ApiClient.ServicesClient.IsValidShortLivedIdentityTokenAsync(token);

                    if (isValid)
                    {
                        await Link(Context.User, user, id, encoded);
                    }
                    else
                    {
                        await ReplyAsync(Context.User.Mention + ", " + "Invalid token! Try creating a new one!");

                        await Context.Message.DeleteAsync();
                    }
                }
                catch (Exception e)
                {
                    await ReplyAsync(Context.User.Mention + ", " + "Invalid verification token : " + e.Message);
                }
            }
        }
コード例 #26
0
        async Task Link(IUser discordUser, TownUser user, int altaId, string linkToken)
        {
            if (user.AltaInfo == null)
            {
                user.AltaInfo = new UserAltaInfo();
            }

            if (user.AltaInfo.Identifier == altaId)
            {
                await ReplyAsync(discordUser.Mention + ", " + "Already connected!");

                await Context.Message.DeleteAsync();

                await AccountService.UpdateAsync(user, (SocketGuildUser)discordUser);

                return;
            }

            if (user.AltaInfo.Identifier != 0)
            {
                await ReplyAsync(discordUser.Mention + ", " + $"Unlinking your Discord from {user.AltaInfo.Username}...");

                await Context.Message.DeleteAsync();

                user.Unlink();

                Database.Users.Update(user);
            }

            TownUser existing = Database.Users.FindByIndex(altaId, "alta_id-index", "AltaId");

            if (existing != null && existing.UserId != discordUser.Id)
            {
                var olddiscorduser = Context.Client.GetUser(existing.UserId);

                await ReplyAsync(discordUser.Mention + ", " + $"Unlinking your Alta account from {olddiscorduser?.Mention}...");

                await Context.Message.DeleteAsync();

                existing.Unlink();

                Database.Users.Update(existing);
            }

            var userInfo = await AltaApi.ApiClient.UserClient.GetUserInfoAsync(altaId);

            user.AltaId = altaId;
            user.AltaInfo.Identifier = altaId;
            user.AltaInfo.Username   = userInfo.Username;

            Database.Users.Update(user);

            try
            {
                if (linkToken != null)
                {
                    await AltaApi.ApiClient.Account.LinkDiscordAccount(linkToken, discordUser.Id);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Failed linking to discord in the ATT Database");
            }

            await ReplyAsync(Context.User.Mention + ", " + $"Successfully linked to your Alta account! Hey there {user.AltaInfo.Username}!");

            await Context.Message.DeleteAsync();

            //await AccountService.UpdateAsync(user, (SocketGuildUser)discordUser);
        }
コード例 #27
0
        public async Task Joined(IUser discordUser)
        {
            TownUser user = Database.GetUser(discordUser);

            await ReplyAsync($"{discordUser.Username} joined on {user.InitialJoin.ToString("dd/MMM/yyyy")}");
        }
コード例 #28
0
		public async Task UpdateAsync(TownUser townUser, SocketGuildUser user)
		{
			if (guild == null)
			{
				guild = Client.GetGuild(Database.Guilds.FindOne(item => true).GuildId);
			}
						
			try
			{
				UserInfo userInfo = await AltaApi.ApiClient.UserClient.GetUserInfoAsync(townUser.AltaInfo.Identifier);
				
				MembershipStatusResponse result = await AltaApi.ApiClient.UserClient.GetMembershipStatus(townUser.AltaInfo.Identifier);

				if (userInfo == null)
				{
					Console.WriteLine("Couldn't find userinfo for " + townUser.Name);
					return;
				}

				if (townUser.AltaInfo != null && townUser.AltaInfo.IsSupporter)
				{
					Console.WriteLine("Couldn't find membership status for " + townUser.Name);
					return;
				}

				townUser.AltaInfo.SupporterExpiry = result.ExpiryTime ?? DateTime.MinValue;
				townUser.AltaInfo.IsSupporter = result.IsMember;
				townUser.AltaInfo.Username = userInfo.Username;

				Console.WriteLine("JUST UPDATED: " + userInfo.Username);

				if (user == null)
				{
					user = guild.GetUser(townUser.UserId);
				}

				if (user == null)
				{
					Console.WriteLine("Couldn't find Discord user for " + townUser.Name + " " + townUser.UserId);
					return;
				}

				if (supporterRole == null)
				{
					supporterRole = guild.GetRole(547202953505800233);
					supporterChannel = guild.GetTextChannel(547204432144891907);
					generalChannel = guild.GetChannel(334933825383563266) as SocketTextChannel;
				}

				if (townUser.AltaInfo.IsSupporter)
				{
					if (user.Roles == null || !user.Roles.Contains(supporterRole))
					{
						try
						{
							await user.AddRoleAsync(supporterRole);
						}
						catch (Exception)
						{
							Console.WriteLine("Error adding role");
							Console.WriteLine(user);
							Console.WriteLine(supporterRole);
						}

						if (user.Roles != null)
						{
							await supporterChannel.SendMessageAsync($"{user.Mention} joined. Thanks for the support!");
							await generalChannel.SendMessageAsync($"{user.Mention} became a supporter! Thanks for the support!\nIf you'd like to find out more about supporting, visit https://townshiptale.com/supporter");
						}
					}
				}
				else if (user.Roles != null && user.Roles.Contains(supporterRole))
				{
					Console.WriteLine("UNSUPPORT : " + user.Username);

					await user.SendMessageAsync("Oh no! You've lost your supporter role! It's been great having you with us in #supporter-chat. If you didn't mean to unsupport, check the Support page in your launcher ( or https://townshiptale.com/supporter ) to be sure your payment didn't fail. If you think this was a mistake, be sure to contact Joel, and he'll help you out!");

					await user.RemoveRoleAsync(supporterRole);
				}

				Database.Users.Update(townUser);
			}
			catch (Exception e)
			{
				Console.WriteLine("Error updating " + townUser.Name);
				Console.WriteLine(e.Message);
			}
		}