public async Task StartAsync(RiftEvent dbEvent, ulong startedById) { if (dbEvent is null) { RiftBot.Log.Warning("Wrong event name, skipping execution."); return; } var msg = await messageService.GetMessageFromApi(dbEvent.MessageId); if (msg is null) { RiftBot.Log.Warning("Wrong event message ID, skipping execution."); return; } var dbSharedReward = await DB.Rewards.GetAsync(dbEvent.SharedRewardId); if (dbSharedReward is null) { RiftBot.Log.Warning("Wrong event reward ID, skipping execution."); return; } if (!IonicHelper.GetEmote(213672490491314176, "smite", out var smite)) { RiftBot.Log.Warning("No event emote, skipping execution."); return; } var activeGiveaway = new RiftActiveEvent { EventName = dbEvent.Name, MessageId = dbEvent.MessageId, StartedBy = startedById == 0u ? IonicHelper.Client.CurrentUser.Id : startedById, StartedAt = DateTime.UtcNow, DueTime = DateTime.UtcNow + dbEvent.Duration, }; var formattedMsg = await messageService.FormatMessageAsync(msg, new FormatData(startedById)); var eventMessage = await messageService.SendMessageAsync(formattedMsg, Settings.ChannelId.Monsters).ConfigureAwait(false); activeGiveaway.ChannelMessageId = eventMessage.Id; await DB.ActiveEvents.AddAsync(activeGiveaway).ConfigureAwait(false); await eventMessage.AddReactionAsync(smite); await ScheduleTimerToClosestActiveAsync().ConfigureAwait(false); }
async Task FinishAsync(RiftActiveEvent expiredEvent) { var eventLogString = $"ID {expiredEvent.Id.ToString()} \"{expiredEvent.EventName}\""; var dbEvent = await DB.Events.GetAsync(expiredEvent.EventName); if (dbEvent is null) { RiftBot.Log.Error($"Could not finish event {eventLogString}: {nameof(RiftEvent)} is null!"); return; } if (!IonicHelper.GetTextChannel(Settings.App.MainGuildId, Settings.ChannelId.Monsters, out var channel)) { RiftBot.Log.Error($"Could not finish event {eventLogString}: Event channel is null!"); return; } var message = (IUserMessage)await channel.GetMessageAsync(expiredEvent.ChannelMessageId); if (message is null) { RiftBot.Log.Error($"Could not finish event {eventLogString}: Event message is null! Deleted?"); return; } if (!IonicHelper.GetEmote(213672490491314176ul, "smite", out var emote)) { RiftBot.Log.Error($"Could not finish event {eventLogString}: Emote is null! Deleted?"); return; } // Reaction amount is limited by discord itself. // See https://discordapp.com/developers/docs/resources/channel#get-reactions var reactions = await message.GetReactionUsersAsync(emote, 100).FlattenAsync(); if (reactions is null) { RiftBot.Log.Error($"Could not finish event {eventLogString}: Unable to get reactions."); return; } var dbReward = await DB.Rewards.GetAsync(dbEvent.SharedRewardId); if (dbReward is null) { RiftBot.Log.Error($"Could not finish event {eventLogString}: " + $"Unable to get reward ID {dbEvent.SharedRewardId.ToString()}."); return; } var participants = reactions .Where(x => !x.IsBot && x.Id != IonicHelper.Client.CurrentUser.Id) .Select(x => x.Id) .ToArray(); if (participants.Length == 0) { await LogEventAsync(dbEvent.Name, null, "No reward provided ", expiredEvent.StartedBy, expiredEvent.StartedAt, dbEvent.Duration); await DB.ActiveEvents.RemoveAsync(expiredEvent.Id); RiftBot.Log.Error($"Could not finish event {eventLogString}: No participants."); return; } RiftReward specialReward = null; var specialWinnerId = 0ul; if (dbEvent.HasSpecialReward) { specialReward = await DB.Rewards.GetAsync(dbEvent.SpecialRewardId); if (specialReward is null) { RiftBot.Log.Error($"Could not finish event {eventLogString}: " + $"Unable to get special reward ID {dbEvent.SharedRewardId.ToString()}."); return; } specialWinnerId = participants.Random(); var specReward = specialReward.ToRewardBase(); await rewardService.DeliverToAsync(specialWinnerId, specReward); } var reward = dbReward.ToRewardBase(); foreach (var userId in participants) { await rewardService.DeliverToAsync(userId, reward); } await DB.ActiveEvents.RemoveAsync(expiredEvent.Id); var eventType = (EventType)dbEvent.Type; foreach (var participant in participants) { switch (eventType) { case EventType.Normal: NormalMonstersKilled?.Invoke( null, new NormalMonstersKilledEventArgs(participant, 1u)); break; case EventType.Rare: RareMonstersKilled?.Invoke( null, new RareMonstersKilledEventArgs(participant, 1u)); break; case EventType.Epic: EpicMonstersKilled?.Invoke( null, new EpicMonstersKilledEventArgs(participant, 1u)); break; } } var log = new RiftEventLog { Name = dbEvent.Name, ParticipantsAmount = (uint)participants.Length, Reward = "No reward provided", StartedBy = expiredEvent.StartedBy, StartedAt = expiredEvent.StartedAt, Duration = dbEvent.Duration, FinishedAt = DateTime.UtcNow, SpecialWinnerId = specialWinnerId }; await messageService.SendMessageAsync("event-finished", Settings.ChannelId.Monsters, new FormatData(expiredEvent.StartedBy) { EventData = new EventData { Log = log, Stored = dbEvent, } }); if (dbEvent.HasSpecialReward) { await messageService.SendMessageAsync("event-finished-special", Settings.ChannelId.Monsters, new FormatData(specialWinnerId) { Reward = specialReward.ToRewardBase() }); } await LogEventAsync(log).ConfigureAwait(false); }
async Task FinishGiveawayAsync(RiftActiveGiveaway expiredGiveaway) { var dbGiveaway = await DB.Giveaways.GetAsync(expiredGiveaway.GiveawayName); var giveawayData = $"ID {expiredGiveaway.Id.ToString()} \"{expiredGiveaway.GiveawayName}\""; if (dbGiveaway is null) { RiftBot.Log.Error($"Could not finish giveaway {giveawayData}: {nameof(RiftGiveaway)} is null!"); return; } if (!IonicHelper.GetTextChannel(Settings.App.MainGuildId, Settings.ChannelId.Chat, out var channel)) { RiftBot.Log.Error($"Could not finish giveaway {giveawayData}: Giveaway channel is null!"); return; } var message = (IUserMessage)await channel.GetMessageAsync(expiredGiveaway.ChannelMessageId); if (message is null) { RiftBot.Log.Error($"Could not finish giveaway {giveawayData}: Giveaway message is null! Deleted?"); return; } if (!IonicHelper.GetEmote(403616665603932162, "giveaway", out var emote)) { RiftBot.Log.Error($"Could not finish giveaway {giveawayData}: Emote is null! Deleted?"); return; } // Reaction amount is limited by discord itself. // See https://discordapp.com/developers/docs/resources/channel#get-reactions var reactions = await message.GetReactionUsersAsync(emote, 100).FlattenAsync(); if (reactions is null) { RiftBot.Log.Error($"Could not finish giveaway {giveawayData}: Unable to get reactions."); return; } var dbReward = await DB.Rewards.GetAsync(dbGiveaway.RewardId); if (dbReward is null) { RiftBot.Log.Error($"Could not finish giveaway {giveawayData}: " + $"Unable to get reward ID {dbGiveaway.RewardId.ToString()}."); return; } var reward = dbReward.ToRewardBase(); var participants = reactions .Where(x => !x.IsBot && x.Id != IonicHelper.Client.CurrentUser.Id) .Select(x => x.Id) .ToArray(); if (participants.Length == 0) { await LogGiveawayAsync(dbGiveaway.Name, null, null, "No reward provided", expiredGiveaway.StartedBy, expiredGiveaway.StartedAt, dbGiveaway.Duration); await DB.ActiveGiveaways.RemoveAsync(expiredGiveaway.Id); RiftBot.Log.Error($"Could not finish giveaway {giveawayData}: No participants."); return; } var winners = new ulong[dbGiveaway.WinnersAmount]; if (participants.Length < dbGiveaway.WinnersAmount) { RiftBot.Log.Error($"Could not finish giveaway {giveawayData}: " + $"Not enough participants: only {participants.Length.ToString()} of minimum {dbGiveaway.WinnersAmount.ToString()}"); return; } if (participants.Length == dbGiveaway.WinnersAmount) { Array.Copy(participants, winners, dbGiveaway.WinnersAmount); } else { ulong winnerId; for (var i = 0; i < dbGiveaway.WinnersAmount; i++) { do { winnerId = participants.Random(); } while (winners.Contains(winnerId)); winners[i] = winnerId; } } foreach (var winner in winners) { await rewardService.DeliverToAsync(winner, reward); } await DB.ActiveGiveaways.RemoveAsync(expiredGiveaway.Id); foreach (var participant in participants) { GiveawaysParticipated?.Invoke(null, new GiveawaysParticipatedEventArgs(participant)); } var log = new RiftGiveawayLog { Name = dbGiveaway.Name, Winners = winners, Participants = participants, Reward = "No reward provided", StartedBy = expiredGiveaway.StartedBy, StartedAt = expiredGiveaway.StartedAt, Duration = dbGiveaway.Duration, FinishedAt = DateTime.UtcNow, }; await messageService.SendMessageAsync("giveaway-finished", Settings.ChannelId.Chat, new FormatData(expiredGiveaway.StartedBy) { Giveaway = new GiveawayData { Log = log, Stored = dbGiveaway, }, Reward = reward }); await LogGiveawayAsync(log).ConfigureAwait(false); }
public async Task StartGiveawayAsync(string name, ulong startedById) { if (string.IsNullOrWhiteSpace(name)) { RiftBot.Log.Warning("Empty giveaway name, skipping execution."); return; } var giveaway = await DB.Giveaways.GetAsync(name); if (giveaway is null) { RiftBot.Log.Warning("Wrong giveaway name, skipping execution."); return; } var msg = await messageService.GetMessageFromApi(giveaway.MessageId); if (msg is null) { RiftBot.Log.Warning("Wrong giveaway message ID, skipping execution."); return; } var dbReward = await DB.Rewards.GetAsync(giveaway.RewardId); if (dbReward is null) { RiftBot.Log.Warning("Wrong giveaway reward ID, skipping execution."); return; } var reward = dbReward.ToRewardBase(); if (!IonicHelper.GetEmote(403616665603932162, "giveaway", out var smite)) { RiftBot.Log.Warning("No giveaway emote, skipping execution."); return; } var activeGiveaway = new RiftActiveGiveaway { GiveawayName = giveaway.Name, MessageId = giveaway.MessageId, StartedBy = startedById == 0u ? IonicHelper.Client.CurrentUser.Id : startedById, StartedAt = DateTime.UtcNow, DueTime = DateTime.UtcNow + giveaway.Duration, }; var formattedMsg = await messageService.FormatMessageAsync( msg, new FormatData(startedById) { Giveaway = new GiveawayData { Stored = giveaway }, Reward = reward }); var giveawayMessage = await messageService.SendMessageAsync(formattedMsg, Settings.ChannelId.Chat).ConfigureAwait(false); activeGiveaway.ChannelMessageId = giveawayMessage.Id; await DB.ActiveGiveaways.AddAsync(activeGiveaway).ConfigureAwait(false); await giveawayMessage.AddReactionAsync(smite); await ScheduleTimerToClosest().ConfigureAwait(false); }