Beispiel #1
0
        public void AddGiveaway(GiveawayEntry entry, ulong serverId)
        {
            GiveawaySchedulerData data = new GiveawaySchedulerData(entry, serverId);
            string json = JsonConvert.SerializeObject(data);

            m_scheduler.Add <GiveawayService>(entry.End, nameof(GiveawaySchedulerCallback), json);
        }
Beispiel #2
0
        public async Task ExecuteGiveaway(GiveawayEntry entry, ulong serverId)
        {
            IGuild guild = await m_client.GetGuildAsync(serverId);

            ServerEntry  server  = m_db.GetServerEntry(serverId);
            ITextChannel channel = await guild.GetTextChannelAsync(entry.ChannelId);

            IUserMessage message = await channel.GetMessageAsync(entry.ReactionMessageId) as IUserMessage;

            var asyncparticipants     = message.GetReactionUsersAsync(new Emoji(server.GiveawayReactionEmote), int.MaxValue);
            IEnumerable <IUser> users = await asyncparticipants.FlattenAsync();

            List <IUser> participants = users.Where(user => user.Id != m_client.CurrentUser.Id).ToList();

            List <IUser> winners = new List <IUser>();

            if (participants.Count <= 0)
            {
                await channel.SendMessageAsync($"No one participated for {entry.Content}");
            }
            else
            {
                for (int i = 0; i < entry.Count; i++)
                {
                    IUser winner;
                    do
                    {
                        winner = participants[m_random.Next(0, participants.Count)];
                    } while(winners.Contains(winner) && entry.Count < participants.Count);
                    winners.Add(winner);
                }

                await channel.SendMessageAsync($"{string.Join(' ', winners.Select(winner => winner.Mention))} won **{entry.Content}**!");
            }
        }
        public void DeleteGiveawayEntry(int giveawayEntryId)
        {
            GiveawayEntry targetGiveawayEntry = context.GiveawayEntries.Find(giveawayEntryId);

            if (targetGiveawayEntry != null)
            {
                context.GiveawayEntries.Remove(targetGiveawayEntry);
            }
        }
        public void UpdateGiveawayEntry(GiveawayEntry giveawayEntry)
        {
            GiveawayEntry targetGiveawayEntry = context.GiveawayEntries.Find(giveawayEntry.GiveawayEntryID);

            if (targetGiveawayEntry != null)
            {
                targetGiveawayEntry.EntryDate  = giveawayEntry.EntryDate;
                targetGiveawayEntry.HasDonated = giveawayEntry.HasDonated;
                targetGiveawayEntry.UserID     = giveawayEntry.UserID;
            }
        }
Beispiel #5
0
        public async Task CreateGiveawayAsync([Summary("Time giveaway will last(ex. 2 days)")] string time, [Summary("What to give away")] string content, uint count = 1)
        {
            if (!DateTimeHelper.TryParseRelative(time, out DateTime end))
            {
                await ReplyAsync("Couldn't parse time");
            }

            ServerEntry server = DatabaseService.GetServerEntry(Context.Guild.Id);

            Embed embed = new EmbedBuilder()
                          .WithColor(0xF5CD63)
                          .WithAuthor(author => {
                author
                .WithName($"{Context.Message.Author.Username} has started a giveaway!")
                .WithIconUrl($"{Context.Message.Author.GetAvatarUrl()}");
            })
                          .AddField("Details ▼",
                                    $"► Prize: __**{content}**__\n" +
                                    $"► Time Limit: **{end.Date}** \n" +
                                    $"► Winner Limit: **{count}** " +
                                    $"**React with {server.GiveawayReactionEmote} to enter the giveaway!**\n" +
                                    $"I Belfast wish every one of the commanders a good luck!")
                          .WithFooter(footer => {
                footer
                .WithText($"Requested by {Context.User}")
                .WithIconUrl(Context.User.GetAvatarUrl());
            })
                          .Build();

            IUserMessage message = await ReplyAsync(embed : embed);

            GiveawayEntry entry = new GiveawayEntry
            {
                End               = end,
                ChannelId         = Context.Channel.Id,
                Content           = content,
                ReactionMessageId = message.Id,
                Count             = count,
            };
            await message.AddReactionAsync(new Emoji(server.GiveawayReactionEmote));

            GiveawayService.AddGiveaway(entry, Context.Guild.Id);
        }
Beispiel #6
0
        /// <summary>
        /// Removes a <see cref="GiveawayEntry"/> from either the entries list or winners list.
        /// </summary>
        /// <param name="item">Item to be removed from selected list.</param>
        /// <param name="fromWinnersList">True if item is to be removed from the winners list.</param>
        private void RemoveSelectedItem(GiveawayEntry item, bool fromWinnersList)
        {
            if (item != null)
            {
                if (fromWinnersList)
                {
                    // Remove item from winners list
                    _listWinners.Remove(item);

                    // Save changed winners list
                    SaveSettings();
                }
                else
                {
                    // Remove item from entries list
                    _listEntries.Remove(item);
                    if (_listEntries.Count == 0)
                    {
                        IsHavingEntries = false;
                    }
                }
            }
        }
 public void InsertGiveawayEntry(GiveawayEntry giveawayEntry)
 {
     context.GiveawayEntries.Add(giveawayEntry);
 }
Beispiel #8
0
 public GiveawaySchedulerData(GiveawayEntry entry, ulong serverId)
 {
     this.entry    = entry;
     this.serverId = serverId;
 }
Beispiel #9
0
        /// <summary>
        /// Initializes a new Giveaway module, seperate from other modules.
        /// </summary>
        /// <param name="id">Id of the module, must be unique and can't be lower than 1.</param>
        /// <param name="rndGen">A preseeded pseudo random generator to be used in the module.</param>
        /// <param name="ccs">Chat Service to receive and send messages.</param>
        /// <param name="wes">WebSocket Event Service to push out giveaway events to websocket.</param>
        public GiveawayViewModel(int id, Random rndGen, IChatConnectionService ccs, IWebSocketEventService wes)
        {
            // Store references
            _moduleId       = id;
            _rndGen         = rndGen;
            _chatService    = ccs;
            _wsEventService = wes;

            // Initialize collections and lists
            _listEntries        = new ObservableCollection <GiveawayEntry>();
            _listWinners        = new ObservableCollection <GiveawayEntry>();
            _listMessagesWinner = new ObservableCollection <TwitchChatMessage>();

            // Initialize MediaPlayer
            _mediaPlayer = new MediaPlayer();

            // Set initial timestamps and spans
            _timestampOpened       = new DateTime(0);
            _timestampClosed       = new DateTime(0);
            _timestampDraw         = new DateTime(0);
            _elapsedOpenTime       = new TimeSpan(0);
            _elapsedNoResponseTime = new TimeSpan(0);
            _elapsedInterval       = new TimeSpan(0, 0, 1);

            // Initialize timers
            _timerOpen = new Timer()
            {
                AutoReset = false
            };
            _timerOpen.Elapsed += _TimerOpen_Elapsed;
            _timerResponse      = new Timer()
            {
                AutoReset = false
            };
            _timerResponse.Elapsed += _TimerResponse_Elapsed;
            _timerElapsed           = new Timer(_elapsedInterval.TotalMilliseconds);
            _timerElapsed.Elapsed  += _TimerElapsed_Elapsed;
            _timerElapsed.Start();

            // Set a 'winner' to display
            _selectedWinner = new GiveawayEntry {
                DisplayName = "WINNER"
            };
            _WinnerHasReplied = true;

            // Load in previous saved settings else use new default settings
            var loaded = BinaryFile.ReadBinFile($"GivewawayModule{ID}");

            if (loaded != null && loaded is GiveawayModuleSettings)
            {
                // Success, set last saved settings and set previous winners
                _moduleSettings = (GiveawayModuleSettings)loaded;
                if (_moduleSettings.SavedWinnersList?.Count > 0)
                {
                    _listWinners = new ObservableCollection <GiveawayEntry>(_moduleSettings.SavedWinnersList);
                }
            }
            else
            {
                // Failure, load defaults
                _moduleSettings = new GiveawayModuleSettings();
            }

            // Transmit WS event
            _wsEventService.SendRegisteredEvent("GIVEAWAY_DONE",
                                                new GiveawayWebsocketEventBase(_moduleId));

            // Register to service events and system broadcast messages
            _chatService.ChatMessageReceived += _chatService_ChatMessageReceived;
        }
Beispiel #10
0
        /// <summary>
        /// Draws a winner from the created drawlist. Will close the giveaway is still active.
        /// </summary>
        /// <param name="redraw">Indication if the previous winner should be redrawn.</param>
        private async void Draw(bool redraw = false)
        {
            // Ignore if giveaway is closing up or no entries left
            // also ignore it if system is already is drawing a winner
            if (_isClosing || _isDrawingWinner || !_isHavingEntries)
            {
                return;
            }

            // Set control flags
            IsDrawingWinner = true;

            // Stop response timer while determining a new winner
            _timerResponse.Stop();
            ElapsedNoResponseTime = new TimeSpan(0);

            // Close first if still active
            Close();

            // Remove the 'previous' winner from the winners list if this is
            // a redraw and the winner has replied by message or default win
            if (redraw && _WinnerHasReplied)
            {
                // Remove previous replied winner from winners list
                GiveawayEntry previous = SelectedWinner;
                await DispatcherHelper.RunAsync(() =>
                {
                    _listWinners.Remove(previous);
                });

                // Save changed winners list after winners list has updated
                SaveSettings();
            }

            // Clear 'previous' winners response messages
            DispatcherHelper.CheckBeginInvokeOnUI(() =>
            {
                _listMessagesWinner.Clear();
            });

            // If there are no more entries to draw from...
            if (_listEntries.Count == 0)
            {
                // Set control flags
                IsDrawingWinner = false;
                IsHavingEntries = false;

                // For UI
                SelectedWinner = new GiveawayEntry {
                    DisplayName = "NOBODY"
                };
                WinnerHasReplied = true;

                // Send chat message with info
                _chatService.SendMessage("There are no entries left to draw from so nobody has won.", false);

                // Transmit WS event
                _wsEventService.SendRegisteredEvent("GIVEAWAY_DONE",
                                                    new GiveawayWebsocketEventBase(_moduleId));

                // Stop Draw function
                return;
            }

            // Draw random winner from the shuffled drawing list
            SelectedWinner = _drawList[_rndGen.Next(0, (_drawList.Count * 4) % _drawList.Count)];

            // Remove picked winner from the draw list and entries list
            _drawList.RemoveAll(x => x == SelectedWinner);
            DispatcherHelper.CheckBeginInvokeOnUI(() =>
            {
                _listEntries.Remove(SelectedWinner);
            });

            // If follow required validate follow with Twitch API
            // Skips follow check if selected winner is a subscriber
            if (_moduleSettings.FollowingRequired && !SelectedWinner.IsSubscriber)
            {
                try
                {
                    // Check if user is following the channel via Twitch API
                    if (await TwitchAPI.GetUserIsFollowingTargetBool(SelectedWinner.UserId, SelectedWinner.ChannelId))
                    {
                        // Silently redraw
                        IsDrawingWinner = false;
                        Draw(true);
                        return;
                    }
                }
                catch
                {
                    // Api Error, allow win due to not be able to verify follow
                }
            }

            // Set timestamp of the draw
            _timestampDraw = DateTime.UtcNow;

            // Require response timer and/or exclude subs from having to respond
            if ((_moduleSettings.ExcludeSubscriberToRespond && SelectedWinner.IsSubscriber) || _moduleSettings.ResponseTimeSeconds < 10)
            {
                // Send chat message of the new winner, no reply required
                string message = $"{SelectedWinner} you have won the giveaway for '{Prize}'!";
                _chatService.SendMessage(message, false);

                // Control, winner does not have to reply
                WinnerHasReplied = true;

                // Add winner to winners list
                await DispatcherHelper.RunAsync(() =>
                {
                    _listWinners.Add(SelectedWinner);
                });

                // Transmit WS event
                _wsEventService.SendRegisteredEvent("GIVEAWAY_DONE",
                                                    new GiveawayWebsocketEventBase(_moduleId));

                // Save current winners list after winners list is done updating
                SaveSettings();
            }
            else
            {
                // Send chat message of the new winner, timed response
                string message = $"{SelectedWinner} you have won the giveaway for '{Prize}'! ";
                message += $"Please reply within {ResponseTimeSeconds} seconds in the chat to claim your prize. ";
                _chatService.SendMessage(message, false);

                // Start response timers and set control flag
                _timerResponse.Interval = (ResponseTimeSeconds * 1000);
                _timerResponse.Start();
                WinnerHasReplied = false;

                // Transmit WS event
                _wsEventService.SendRegisteredEvent("GIVEAWAY_DRAW",
                                                    new GiveawayWebsocketEventDraw(_moduleId, _moduleSettings, _timestampDraw, _selectedWinner));
            }

            // Done drawing a winner, unlock
            IsDrawingWinner = false;
        }
Beispiel #11
0
        /// <summary>
        /// Open a new giveaway if one is not already started or is in the process of drawing a winner.
        /// </summary>
        /// <param name="reopen">Does not clear entries list if set to true.</param>
        private void Open(bool reopen = false)
        {
            // Ignore if giveaway is already active else set active
            if (_isActive || _isClosing || _isDrawingWinner)
            {
                return;
            }

            // Set control flags
            IsActive = true;

            // Clear 'previous' winner messages if any
            DispatcherHelper.CheckBeginInvokeOnUI(() =>
            {
                _listMessagesWinner.Clear();
            });

            // Behavior and message on open or reopen action
            if (reopen)
            {
                // Send a Chat Message with reopened info
                string message = $"A giveaway for '{Prize}' has reopened";
                message += OpenTimeMinutes > 0 ? $" for another {OpenTimeMinutes} minutes! " : "! ";
                message += IsFollowRequired ? "Following the channel is required to be eligible to win. " : "";
                message += $"Type in '{Keyword}' to enter this giveaway, if you already have entered before you don't have to type again.";
                _chatService.SendMessage(message, false);
            }
            else
            {
                // Set control flag
                IsHavingEntries = false;

                // Set 'winner' to display
                SelectedWinner = new GiveawayEntry {
                    DisplayName = "WINNER"
                };
                ElapsedNoResponseTime = new TimeSpan(0);

                // Clear entries list on UI thread
                DispatcherHelper.CheckBeginInvokeOnUI(() =>
                {
                    _listEntries.Clear();
                });

                // Send new giveaway opened message
                string message = $"A giveaway for '{Prize}' has opened";
                message += OpenTimeMinutes > 0 ? $" for {OpenTimeMinutes} minutes! " : "! ";
                message += IsFollowRequired ? "Following the channel is required to be eligible to win. " : "";
                message += $"Type in '{Keyword}' to enter this giveaway.";
                _chatService.SendMessage(message, false);
            }

            // Set opened timestamp and reset elapsed open timespan
            _timestampOpened = DateTime.UtcNow;
            ElapsedOpenTime  = new TimeSpan(0);

            // Start open timer if required
            if (OpenTimeMinutes > 0)
            {
                _timerOpen.Interval = (OpenTimeMinutes * 60000);
                _timerOpen.Start();
            }

            // Transmit WS event
            _wsEventService.SendRegisteredEvent("GIVEAWAY_OPENED",
                                                new GiveawayWebsocketEventOpen(_moduleId, _moduleSettings, _timestampOpened, _listEntries.Count));

            // Save current settings values to file
            SaveSettings();
        }