mirror of
https://github.com/Jetsparrow/karmabot.git
synced 2026-01-21 00:56:09 +03:00
Make everything asynchronous
This commit is contained in:
parent
5e239c934c
commit
a1b5db8430
@ -1,10 +1,12 @@
|
||||
using JetKarmaBot.Commands;
|
||||
using JetKarmaBot.Services;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NLog;
|
||||
using Perfusion;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Telegram.Bot;
|
||||
using Telegram.Bot.Args;
|
||||
|
||||
@ -22,7 +24,7 @@ namespace JetKarmaBot
|
||||
BotUser = botUser;
|
||||
}
|
||||
|
||||
public bool Execute(object sender, MessageEventArgs args)
|
||||
public async Task<bool> Execute(object sender, MessageEventArgs args)
|
||||
{
|
||||
log.Debug("Message received");
|
||||
var text = args.Message.Text;
|
||||
@ -40,27 +42,33 @@ namespace JetKarmaBot
|
||||
if (commands.ContainsKey(cmd.Command))
|
||||
{
|
||||
log.Debug($"Handling message via {commands[cmd.Command].GetType().Name}");
|
||||
return commands[cmd.Command].Execute(cmd, args);
|
||||
return await commands[cmd.Command].Execute(cmd, args);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.Error($"Error while handling command {cmd.Command}!");
|
||||
log.Error(e);
|
||||
ReportToAdministratorChats($"Error while handling command {cmd.Command}!\n{e.ToString()}");
|
||||
await ReportToAdministratorChats($"Error while handling command {cmd.Command}!\n{e.ToString()}");
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void ReportToAdministratorChats(string text)
|
||||
public async Task ReportToAdministratorChats(string text)
|
||||
{
|
||||
using (var db = Db.GetContext())
|
||||
{
|
||||
await Task.WhenAll(
|
||||
(await db.Chats
|
||||
.Where(x => x.IsAdministrator)
|
||||
.Select(x => x.ChatId)
|
||||
.ToArrayAsync())
|
||||
.Select(x => Client.SendTextMessageAsync(x, text)));
|
||||
foreach (long chatid in db.Chats.Where(x => x.IsAdministrator).Select(x => x.ChatId))
|
||||
{
|
||||
Client.SendTextMessageAsync(chatid, text);
|
||||
await Client.SendTextMessageAsync(chatid, text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,6 +7,8 @@ using Telegram.Bot.Types;
|
||||
using Perfusion;
|
||||
using JetKarmaBot.Services;
|
||||
using NLog;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace JetKarmaBot.Commands
|
||||
{
|
||||
@ -16,14 +18,14 @@ namespace JetKarmaBot.Commands
|
||||
[Inject]
|
||||
private Logger log;
|
||||
|
||||
public bool Execute(CommandString cmd, MessageEventArgs args)
|
||||
public async Task<bool> Execute(CommandString cmd, MessageEventArgs args)
|
||||
{
|
||||
using (var db = Db.GetContext())
|
||||
{
|
||||
var currentLocale = Locale[db.Chats.Find(args.Message.Chat.Id).Locale];
|
||||
var currentLocale = Locale[(await db.Chats.FindAsync(args.Message.Chat.Id)).Locale];
|
||||
if (args.Message.ReplyToMessage == null)
|
||||
{
|
||||
Client.SendTextMessageAsync(args.Message.Chat.Id, currentLocale["jetkarmabot.award.errawardnoreply"]);
|
||||
await Client.SendTextMessageAsync(args.Message.Chat.Id, currentLocale["jetkarmabot.award.errawardnoreply"]);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -34,7 +36,7 @@ namespace JetKarmaBot.Commands
|
||||
|
||||
if (awarder.Id == recipient.Id)
|
||||
{
|
||||
Client.SendTextMessageAsync(
|
||||
await Client.SendTextMessageAsync(
|
||||
args.Message.Chat.Id,
|
||||
currentLocale["jetkarmabot.award.errawardself"],
|
||||
replyToMessageId: args.Message.MessageId);
|
||||
@ -43,7 +45,7 @@ namespace JetKarmaBot.Commands
|
||||
|
||||
if (Me.Id == recipient.Id)
|
||||
{
|
||||
Client.SendTextMessageAsync(
|
||||
await Client.SendTextMessageAsync(
|
||||
args.Message.Chat.Id,
|
||||
awarding
|
||||
? currentLocale["jetkarmabot.award.errawardbot"]
|
||||
@ -55,18 +57,18 @@ namespace JetKarmaBot.Commands
|
||||
var text = args.Message.Text;
|
||||
var awardTypeText = cmd.Parameters.FirstOrDefault();
|
||||
global::JetKarmaBot.Models.AwardType awardType = awardTypeText != null
|
||||
? db.AwardTypes.First(at => at.CommandName == awardTypeText)
|
||||
: db.AwardTypes.Find((sbyte)1);
|
||||
? await db.AwardTypes.FirstAsync(at => at.CommandName == awardTypeText)
|
||||
: await db.AwardTypes.FindAsync((sbyte)1);
|
||||
DateTime cutoff = DateTime.Now - TimeSpan.FromMinutes(5);
|
||||
if (db.Awards.Where(x => x.Date > cutoff && x.FromId == awarder.Id).Count() >= 10)
|
||||
if (await db.Awards.Where(x => x.Date > cutoff && x.FromId == awarder.Id).CountAsync() >= 10)
|
||||
{
|
||||
Client.SendTextMessageAsync(
|
||||
await Client.SendTextMessageAsync(
|
||||
args.Message.Chat.Id,
|
||||
currentLocale["jetkarmabot.award.ratelimit"],
|
||||
replyToMessageId: args.Message.MessageId);
|
||||
return true;
|
||||
}
|
||||
db.Awards.Add(new Models.Award()
|
||||
await db.Awards.AddAsync(new Models.Award()
|
||||
{
|
||||
AwardTypeId = awardType.AwardTypeId,
|
||||
Amount = (sbyte)(awarding ? 1 : -1),
|
||||
@ -75,21 +77,21 @@ namespace JetKarmaBot.Commands
|
||||
ChatId = args.Message.Chat.Id
|
||||
});
|
||||
log.Debug($"Awarded {(awarding ? 1 : -1)}{awardType.Symbol} to {recipient.Username}");
|
||||
db.SaveChanges();
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
var recUserName = db.Users.Find(recipient.Id).Username;
|
||||
var recUserName = (await db.Users.FindAsync(recipient.Id)).Username;
|
||||
|
||||
string message = awarding
|
||||
? string.Format(currentLocale["jetkarmabot.award.awardmessage"], getLocalizedName(awardType, currentLocale), recUserName)
|
||||
: string.Format(currentLocale["jetkarmabot.award.revokemessage"], getLocalizedName(awardType, currentLocale), recUserName);
|
||||
|
||||
var currentCount = db.Awards
|
||||
var currentCount = await db.Awards
|
||||
.Where(aw => aw.ToId == recipient.Id && aw.AwardTypeId == awardType.AwardTypeId && aw.ChatId == args.Message.Chat.Id)
|
||||
.Sum(aw => aw.Amount);
|
||||
.SumAsync(aw => aw.Amount);
|
||||
|
||||
var response = message + "\n" + String.Format(currentLocale["jetkarmabot.award.statustext"], recUserName, currentCount, awardType.Symbol);
|
||||
|
||||
Client.SendTextMessageAsync(
|
||||
await Client.SendTextMessageAsync(
|
||||
args.Message.Chat.Id,
|
||||
response,
|
||||
replyToMessageId: args.Message.MessageId);
|
||||
|
||||
@ -5,6 +5,7 @@ using Perfusion;
|
||||
using JetKarmaBot.Services;
|
||||
using NLog;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace JetKarmaBot.Commands
|
||||
{
|
||||
@ -14,14 +15,14 @@ namespace JetKarmaBot.Commands
|
||||
[Inject]
|
||||
private Logger log;
|
||||
|
||||
public bool Execute(CommandString cmd, MessageEventArgs args)
|
||||
public async Task<bool> Execute(CommandString cmd, MessageEventArgs args)
|
||||
{
|
||||
using (var db = Db.GetContext())
|
||||
{
|
||||
var currentLocale = Locale[db.Chats.Find(args.Message.Chat.Id).Locale];
|
||||
var currentLocale = Locale[(await db.Chats.FindAsync(args.Message.Chat.Id)).Locale];
|
||||
if (cmd.Parameters.Length < 1)
|
||||
{
|
||||
Client.SendTextMessageAsync(
|
||||
await Client.SendTextMessageAsync(
|
||||
args.Message.Chat.Id,
|
||||
currentLocale["jetkarmabot.changelocale.getlocale"],
|
||||
replyToMessageId: args.Message.MessageId);
|
||||
@ -29,7 +30,7 @@ namespace JetKarmaBot.Commands
|
||||
}
|
||||
else if (cmd.Parameters[0] == "list")
|
||||
{
|
||||
Client.SendTextMessageAsync(
|
||||
await Client.SendTextMessageAsync(
|
||||
args.Message.Chat.Id,
|
||||
currentLocale["jetkarmabot.changelocale.listalltext"] + "\n"
|
||||
+ string.Join("\n", Locale.Select(a => a.Key)),
|
||||
@ -38,7 +39,7 @@ namespace JetKarmaBot.Commands
|
||||
}
|
||||
else if (cmd.Parameters[0] == "all")
|
||||
{
|
||||
Client.SendTextMessageAsync(
|
||||
await Client.SendTextMessageAsync(
|
||||
args.Message.Chat.Id,
|
||||
currentLocale["jetkarmabot.changelocale.errorall"],
|
||||
replyToMessageId: args.Message.MessageId);
|
||||
@ -54,19 +55,19 @@ namespace JetKarmaBot.Commands
|
||||
}
|
||||
catch (LocalizationException e)
|
||||
{
|
||||
Client.SendTextMessageAsync(
|
||||
await Client.SendTextMessageAsync(
|
||||
args.Message.Chat.Id,
|
||||
currentLocale["jetkarmabot.changelocale.toomany"] + "\n" + string.Join("\n", (e.Data["LocaleNames"] as Locale[]).Select(x => x.Name)),
|
||||
replyToMessageId: args.Message.MessageId);
|
||||
return true;
|
||||
}
|
||||
db.Chats.Find(args.Message.Chat.Id).Locale = localeId;
|
||||
(await db.Chats.FindAsync(args.Message.Chat.Id)).Locale = localeId;
|
||||
log.Debug($"Changed language of chat {args.Message.Chat.Id} to {localeId}");
|
||||
db.SaveChanges();
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
currentLocale = Locale[db.Chats.Find(args.Message.Chat.Id).Locale];
|
||||
currentLocale = Locale[(await db.Chats.FindAsync(args.Message.Chat.Id)).Locale];
|
||||
|
||||
Client.SendTextMessageAsync(
|
||||
await Client.SendTextMessageAsync(
|
||||
args.Message.Chat.Id,
|
||||
(currentLocale.HasNote ? currentLocale["jetkarmabot.changelocale.beforenote"] + currentLocale.Note + "\n" : "")
|
||||
+ currentLocale["jetkarmabot.changelocale.justchanged"],
|
||||
|
||||
@ -5,6 +5,8 @@ using JetKarmaBot.Services;
|
||||
using Telegram.Bot;
|
||||
using Telegram.Bot.Types.Enums;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace JetKarmaBot.Commands
|
||||
{
|
||||
@ -21,14 +23,14 @@ namespace JetKarmaBot.Commands
|
||||
public IReadOnlyCollection<ChatCommandArgument> Arguments => new ChatCommandArgument[] {
|
||||
};
|
||||
|
||||
public bool Execute(CommandString cmd, MessageEventArgs args)
|
||||
public async Task<bool> Execute(CommandString cmd, MessageEventArgs args)
|
||||
{
|
||||
using (var db = Db.GetContext())
|
||||
{
|
||||
var currentLocale = Locale[db.Chats.Find(args.Message.Chat.Id).Locale];
|
||||
var currentLocale = Locale[(await db.Chats.FindAsync(args.Message.Chat.Id)).Locale];
|
||||
string resp = currentLocale["jetkarmabot.currencies.listtext"] + "\n" + string.Join("\n",
|
||||
db.AwardTypes.ToList().Select(x => $"{x.Symbol} ({x.CommandName}) <i>{currentLocale["jetkarmabot.awardtypes.nominative." + x.CommandName]}</i>"));
|
||||
Client.SendTextMessageAsync(
|
||||
(await db.AwardTypes.ToListAsync()).Select(x => $"{x.Symbol} ({x.CommandName}) <i>{currentLocale["jetkarmabot.awardtypes.nominative." + x.CommandName]}</i>"));
|
||||
await Client.SendTextMessageAsync(
|
||||
args.Message.Chat.Id,
|
||||
resp,
|
||||
replyToMessageId: args.Message.MessageId,
|
||||
|
||||
@ -4,6 +4,7 @@ using Perfusion;
|
||||
using JetKarmaBot.Services;
|
||||
using Telegram.Bot;
|
||||
using Telegram.Bot.Types.Enums;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace JetKarmaBot.Commands
|
||||
{
|
||||
@ -28,14 +29,14 @@ namespace JetKarmaBot.Commands
|
||||
}
|
||||
};
|
||||
|
||||
public bool Execute(CommandString cmd, MessageEventArgs args)
|
||||
public async Task<bool> Execute(CommandString cmd, MessageEventArgs args)
|
||||
{
|
||||
using (var db = Db.GetContext())
|
||||
{
|
||||
var currentLocale = Locale[db.Chats.Find(args.Message.Chat.Id).Locale];
|
||||
var currentLocale = Locale[(await db.Chats.FindAsync(args.Message.Chat.Id)).Locale];
|
||||
if (cmd.Parameters.Length < 1)
|
||||
{
|
||||
Client.SendTextMessageAsync(
|
||||
await Client.SendTextMessageAsync(
|
||||
args.Message.Chat.Id,
|
||||
Router.GetHelpText(currentLocale),
|
||||
replyToMessageId: args.Message.MessageId,
|
||||
@ -44,7 +45,7 @@ namespace JetKarmaBot.Commands
|
||||
}
|
||||
else
|
||||
{
|
||||
Client.SendTextMessageAsync(
|
||||
await Client.SendTextMessageAsync(
|
||||
args.Message.Chat.Id,
|
||||
Router.GetHelpTextFor(cmd.Parameters[0], currentLocale),
|
||||
replyToMessageId: args.Message.MessageId,
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Telegram.Bot.Args;
|
||||
|
||||
namespace JetKarmaBot.Commands
|
||||
@ -10,7 +11,7 @@ namespace JetKarmaBot.Commands
|
||||
string DescriptionID { get; }
|
||||
IReadOnlyCollection<ChatCommandArgument> Arguments { get; }
|
||||
|
||||
bool Execute(CommandString cmd, MessageEventArgs messageEventArgs);
|
||||
Task<bool> Execute(CommandString cmd, MessageEventArgs messageEventArgs);
|
||||
}
|
||||
|
||||
public struct ChatCommandArgument
|
||||
|
||||
@ -17,11 +17,11 @@ namespace JetKarmaBot.Commands
|
||||
{
|
||||
public IReadOnlyCollection<string> Names => new[] { "leaderboard" };
|
||||
|
||||
public bool Execute(CommandString cmd, MessageEventArgs args)
|
||||
public async Task<bool> Execute(CommandString cmd, MessageEventArgs args)
|
||||
{
|
||||
using (var db = Db.GetContext())
|
||||
{
|
||||
var currentLocale = Locale[db.Chats.Find(args.Message.Chat.Id).Locale];
|
||||
var currentLocale = Locale[(await db.Chats.FindAsync(args.Message.Chat.Id)).Locale];
|
||||
var asker = args.Message.From;
|
||||
var awardTypeName = cmd.Parameters.FirstOrDefault();
|
||||
|
||||
@ -33,19 +33,21 @@ namespace JetKarmaBot.Commands
|
||||
var awardTypeIdQuery = from awt in db.AwardTypes
|
||||
where awt.CommandName == awardTypeName
|
||||
select awt.AwardTypeId;
|
||||
var awardTypeId = awardTypeIdQuery.First();
|
||||
var awardType = db.AwardTypes.Find(awardTypeId);
|
||||
var awardTypeId = await awardTypeIdQuery.FirstAsync();
|
||||
var awardType = await db.AwardTypes.FindAsync(awardTypeId);
|
||||
|
||||
response = string.Format(currentLocale["jetkarmabot.leaderboard.specifictext"], awardType.Symbol) + "\n" + string.Join('\n', db.Awards
|
||||
response = string.Format(currentLocale["jetkarmabot.leaderboard.specifictext"], awardType.Symbol) + "\n" + string.Join('\n',
|
||||
await Task.WhenAll((await db.Awards
|
||||
.Where(x => x.ChatId == args.Message.Chat.Id && x.AwardTypeId == awardTypeId)
|
||||
.GroupBy(x => x.ToId)
|
||||
.Select(x => new { UserId = x.Key, Amount = x.Sum(y => y.Amount) })
|
||||
.OrderByDescending(x => x.Amount)
|
||||
.Take(5)
|
||||
.ToList()
|
||||
.Select((x,index) => $"{index+1}. {db.Users.Find(x.UserId).Username} - {x.Amount}"));
|
||||
.ToListAsync())
|
||||
.Select(async (x, index) => $"{index + 1}. {(await db.Users.FindAsync(x.UserId)).Username} - {x.Amount}"))
|
||||
);
|
||||
|
||||
Client.SendTextMessageAsync(
|
||||
await Client.SendTextMessageAsync(
|
||||
args.Message.Chat.Id,
|
||||
response,
|
||||
replyToMessageId: args.Message.MessageId);
|
||||
|
||||
@ -8,6 +8,8 @@ using Telegram.Bot.Args;
|
||||
using Telegram.Bot.Types;
|
||||
using JetKarmaBot.Models;
|
||||
using JetKarmaBot.Services;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace JetKarmaBot.Commands
|
||||
{
|
||||
@ -15,11 +17,11 @@ namespace JetKarmaBot.Commands
|
||||
{
|
||||
public IReadOnlyCollection<string> Names => new[] { "status" };
|
||||
|
||||
public bool Execute(CommandString cmd, MessageEventArgs args)
|
||||
public async Task<bool> Execute(CommandString cmd, MessageEventArgs args)
|
||||
{
|
||||
using (var db = Db.GetContext())
|
||||
{
|
||||
var currentLocale = Locale[db.Chats.Find(args.Message.Chat.Id).Locale];
|
||||
var currentLocale = Locale[(await db.Chats.FindAsync(args.Message.Chat.Id)).Locale];
|
||||
var asker = args.Message.From;
|
||||
var awardTypeName = cmd.Parameters.FirstOrDefault();
|
||||
|
||||
@ -38,9 +40,11 @@ namespace JetKarmaBot.Commands
|
||||
where award.ToId == asker.Id && award.ChatId == args.Message.Chat.Id
|
||||
group award by award.AwardTypeId into g
|
||||
select new { AwardTypeId = g.Key, Amount = g.Sum(x => x.Amount) };
|
||||
var awardsByType = awardsQuery.ToList();
|
||||
var awardsByType = await awardsQuery.ToListAsync();
|
||||
response = currentLocale["jetkarmabot.status.listalltext"] + "\n"
|
||||
+ string.Join("\n", awardsByType.Select(a => $" - {db.AwardTypes.Find(a.AwardTypeId).Symbol} {a.Amount}"));
|
||||
+ string.Join("\n", await Task.WhenAll(
|
||||
awardsByType.Select(async a => $" - {(await db.AwardTypes.FindAsync(a.AwardTypeId)).Symbol} {a.Amount}")
|
||||
));
|
||||
|
||||
}
|
||||
}
|
||||
@ -49,13 +53,13 @@ namespace JetKarmaBot.Commands
|
||||
var awardTypeIdQuery = from awt in db.AwardTypes
|
||||
where awt.CommandName == awardTypeName
|
||||
select awt.AwardTypeId;
|
||||
var awardTypeId = awardTypeIdQuery.First();
|
||||
var awardType = db.AwardTypes.Find(awardTypeId);
|
||||
var awardTypeId = await awardTypeIdQuery.FirstAsync();
|
||||
var awardType = await db.AwardTypes.FindAsync(awardTypeId);
|
||||
|
||||
response = string.Format(currentLocale["jetkarmabot.status.listspecifictext"], db.Awards.Where(x => x.AwardTypeId == awardTypeId && x.ToId == asker.Id && x.ChatId == args.Message.Chat.Id).Sum(x => x.Amount), awardType.Symbol);
|
||||
response = string.Format(currentLocale["jetkarmabot.status.listspecifictext"], await db.Awards.Where(x => x.AwardTypeId == awardTypeId && x.ToId == asker.Id && x.ChatId == args.Message.Chat.Id).SumAsync(x => x.Amount), awardType.Symbol);
|
||||
}
|
||||
|
||||
Client.SendTextMessageAsync(
|
||||
await Client.SendTextMessageAsync(
|
||||
args.Message.Chat.Id,
|
||||
response,
|
||||
replyToMessageId: args.Message.MessageId);
|
||||
|
||||
@ -55,22 +55,23 @@ namespace JetKarmaBot
|
||||
var message = messageEventArgs.Message;
|
||||
if (message == null || message.Type != MessageType.Text)
|
||||
return;
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
using (KarmaContext db = Db.GetContext())
|
||||
{
|
||||
AddUserToDatabase(db, messageEventArgs.Message.From);
|
||||
await AddUserToDatabase(db, messageEventArgs.Message.From);
|
||||
if (messageEventArgs.Message.ReplyToMessage != null)
|
||||
AddUserToDatabase(db, messageEventArgs.Message.ReplyToMessage.From);
|
||||
await AddUserToDatabase(db, messageEventArgs.Message.ReplyToMessage.From);
|
||||
if (!db.Chats.Any(x => x.ChatId == messageEventArgs.Message.Chat.Id))
|
||||
db.Chats.Add(new Models.Chat { ChatId = messageEventArgs.Message.Chat.Id });
|
||||
db.SaveChanges();
|
||||
await db.SaveChangesAsync();
|
||||
}
|
||||
string s = message.Text;
|
||||
long id = message.Chat.Id;
|
||||
long from = message.From.Id;
|
||||
Task.Run(() => Commands.Execute(sender, messageEventArgs));
|
||||
await Commands.Execute(sender, messageEventArgs);
|
||||
});
|
||||
}
|
||||
|
||||
private void AddUserToDatabase(KarmaContext db, Telegram.Bot.Types.User u)
|
||||
private async Task AddUserToDatabase(KarmaContext db, Telegram.Bot.Types.User u)
|
||||
{
|
||||
string un;
|
||||
if (u.Username == null)
|
||||
@ -78,9 +79,9 @@ namespace JetKarmaBot
|
||||
else
|
||||
un = "@" + u.Username;
|
||||
if (!db.Users.Any(x => x.UserId == u.Id))
|
||||
db.Users.Add(new Models.User { UserId = u.Id, Username = un});
|
||||
await db.Users.AddAsync(new Models.User { UserId = u.Id, Username = un });
|
||||
else
|
||||
db.Users.Find(u.Id).Username = un;
|
||||
(await db.Users.FindAsync(u.Id)).Username = un;
|
||||
}
|
||||
|
||||
void InitCommands(IContainer c)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user