Beispiel #1
0
        private async Task HandleAuthenticatedUserListCommand(
            ITelegramBotApi api,
            Update update,
            User from,
            Chat chat,
            long userId,
            string[] parsedCommand
            )
        {
            UnStop(userId);

            var state = UserState <UserRssSubscriptions> .LoadOrDefault(userId);

            var r = await api.RespondToUpdate(update, $"{from.FirstName}, here are your subscribtions:");

            if (state.Data.RssEntries != null)
            {
                for (int i = 0; i < state.Data.RssEntries.Count; ++i)
                {
                    var entry = state.Data.RssEntries[i];
                    var kws   = string.Join(", ", entry.Keywords);
                    var rr    = await api.RespondToUpdate(update, $"{i}: {entry.Url} {kws}");
                }
            }
        }
Beispiel #2
0
        private async Task HandleAuthenticatedUserHoursCommand(
            ITelegramBotApi api,
            Update update,
            User from,
            Chat chat,
            long userId,
            string[] parsedCommand
            )
        {
            var state = UserState <UserMuteState> .LoadOrDefault(userId);

            if (parsedCommand.Length != 3 ||
                !int.TryParse(parsedCommand[1], out var hoursFrom) ||
                !int.TryParse(parsedCommand[2], out var hoursTo))
            {
                var r1 = await api.RespondToUpdate(update, $"{from.FirstName}, I need arguments");

                return;
            }

            state.Data.SetHours(hoursFrom, hoursTo);
            state.Save();

            var r = await api.RespondToUpdate(update, $"{from.FirstName}, bot will mute notifications when outside [{hoursFrom}:00:00, {hoursTo}:00:00]");
        }
Beispiel #3
0
        private async Task HandleAuthenticatedUserDelCommand(
            ITelegramBotApi api,
            Update update,
            User from,
            Chat chat,
            long userId,
            string[] parsedCommand
            )
        {
            UnStop(userId);

            if (parsedCommand.Length < 2 || !int.TryParse(parsedCommand[1], out var idx))
            {
                var rr = await api.RespondToUpdate(update, $"{from.FirstName}, please give arguments to the command");

                return;
            }

            var state = UserState <UserRssSubscriptions> .LoadOrDefault(userId);

            if (state.Data.RssEntries == null || idx >= state.Data.RssEntries.Count || idx < 0)
            {
                var rr = await api.RespondToUpdate(update, $"{from.FirstName}, index {idx} is not known");

                return;
            }

            state.Data.RssEntries.RemoveAt(idx);
            state.Save();

            var r = await api.RespondToUpdate(update, $"{from.FirstName}, {idx} was removed");
        }
Beispiel #4
0
        private async Task HandleNonAuthenticatedUserCommand(
            ITelegramBotApi api,
            Update update,
            User from,
            Chat chat,
            long userId,
            string[] parsedCommand
            )
        {
            if (parsedCommand.Length == 2 &&
                parsedCommand[0] == "/auth" &&
                parsedCommand[1] == Configuration.BOT_SECRET)
            {
                var state = UserState <UserDetails> .LoadOrDefault(userId);

                state.Data.ChatId = chat.Id;
                state.Data.UserId = userId; // kind of overkill
                state.Save();

                var r = await api.RespondToUpdate(update, $"{from.FirstName}, you are now authenticated");
            }
            else if (parsedCommand.Length > 1 && parsedCommand[0] == "/start")
            {
                await HandleUnauthenticatedUserStartCommand(api, update, from, chat, userId, parsedCommand);
            }
            else
            {
                var r = await api.RespondToUpdate(update, $"{from.FirstName}, access denied");
            }
        }
Beispiel #5
0
        private void UnStop(long userId)
        {
            var state = UserState <UserMuteState> .LoadOrDefault(userId);

            if (state.Data.Stopped)
            {
                state.Data.Stopped = false;
                state.Save();
            }
        }
Beispiel #6
0
        private async Task HandleAuthenticatedUserUnmuteCommand(
            ITelegramBotApi api,
            Update update,
            User from,
            Chat chat,
            long userId,
            string[] parsedCommand
            )
        {
            var state = UserState <UserMuteState> .LoadOrDefault(userId);

            state.Data.Muted = false;
            state.Save();

            var r = await api.RespondToUpdate(update, $"{from.FirstName}, bot un-muted");
        }
Beispiel #7
0
        private async Task HandleUnauthenticatedUserStartCommand(
            ITelegramBotApi api,
            Update update,
            User from,
            Chat chat,
            long userId,
            string[] parsedCommand
            )
        {
            var state = UserState <UserMuteState> .LoadOrDefault(userId);

            state.Data.Stopped = true;
            state.Save();

            var r = await api.RespondToUpdate(update, $"Saluton {from.FirstName}. Estas propra boto, vi bezonas rajto pro uzi gxin");
        }
Beispiel #8
0
        private async Task HandleNonAuthenticatedUserCommand(
            ITelegramBotApi api,
            Update update,
            User from,
            Chat chat,
            long userId,
            string[] parsedCommand
            )
        {
            if (parsedCommand.Length == 2 &&
                parsedCommand[0] == "/auth" &&
                parsedCommand[1] == ApiKeys.BOT_SECRET_AUTH_KEY)
            {
                UserState <AuthValidFlag> .LoadOrDefault(userId).Save();

                var r = await api.RespondToUpdate(update, $"{from.FirstName}, you are now authenticated");
            }
            else
            {
                var r = await api.RespondToUpdate(update, $"{from.FirstName}, access denied");
            }
        }
Beispiel #9
0
        private async Task HandleUserMessageAsync(ITelegramBotApi api, Update update)
        {
            User   from   = update.Message.From;
            Chat   chat   = update.Message.Chat;
            long   userId = update.Message.From.Id;
            string text   = update.Message.Text ?? "";

            string[] commandItems = text.Split(' ');

            if (commandItems.Length < 1)
            {
                return;
            }

            if (UserState <UserDetails> .ExistsFor(userId) && UserState <UserDetails> .LoadOrDefault(userId).Data.AuthValid)
            {
                await HandleAuthenticatedUserCommand(api, update, from, chat, userId, commandItems);
            }
            else
            {
                await HandleNonAuthenticatedUserCommand(api, update, from, chat, userId, commandItems);
            }
        }
Beispiel #10
0
        private async Task HandleAuthenticatedUserAddCommand(
            ITelegramBotApi api,
            Update update,
            User from,
            Chat chat,
            long userId,
            string[] parsedCommand
            )
        {
            UnStop(userId);

            if (parsedCommand.Length < 2)
            {
                var rr = await api.RespondToUpdate(update, $"{from.FirstName}, please give arguments to the command");

                return;
            }

            var state = UserState <UserRssSubscriptions> .LoadOrDefault(userId);

            if (state.Data.RssEntries == null)
            {
                state.Data.RssEntries = new List <RssUrlEntry>();
            }

            state.Data.RssEntries.Add(
                new RssUrlEntry
            {
                Url      = parsedCommand[1],
                Keywords = parsedCommand.Skip(2).ToArray()
            });

            state.Save();

            var r = await api.RespondToUpdate(update, $"{from.FirstName}, it was added");
        }
Beispiel #11
0
        private async Task RunFetcherAsync(UserDetails user)
        {
            var rssDetails = UserState <UserRssSubscriptions> .LoadOrDefault(user.UserId);

            var rssPubDates = UserState <UserFeedPubDates> .LoadOrDefault(user.UserId);

            var muteSettings = UserState <UserMuteState> .LoadOrDefault(user.UserId);

            if (muteSettings.Data.Stopped)
            {
                logger.Info($"Bot is stopped for {user.UserId} -- skipping");
                return;
            }

            var  now     = DateTime.Now;
            bool isMuted = muteSettings.Data.IsMutedNow(ref now);

            logger.Info($"User {user.UserId} has {rssDetails.Data.RssEntries?.Count} feeds");

            if ((rssDetails.Data.RssEntries?.Count ?? 0) == 0)
            {
                return;
            }

            var fetchAndParseTasks =
                rssDetails.Data
                .RssEntries
                .Select(feed => _rssReader.FetchAndParse(feed.Url))
                .ToArray();

            RssFeed[] results = await Task.WhenAll(fetchAndParseTasks);

            if (rssPubDates.Data.PubDates == null)
            {
                rssPubDates.Data.PubDates = new SerializableDictionary <string, DateTime>();
            }

            for (int feedIdx = 0; feedIdx < results.Length; ++feedIdx)
            {
                var feedInfo = rssDetails.Data.RssEntries[feedIdx];
                var feedData = results[feedIdx];

                if (feedData == null)
                {
                    logger.Info($"User {user.UserId}, feed {feedInfo.Url}: fetch/parse failed");
                    continue;
                }

                if (rssPubDates.Data.PubDates.TryGetValue(feedInfo.Url, out var prevPubDate))
                {
                    if (prevPubDate == feedData.LastBuildDate && prevPubDate != DateTime.MinValue)
                    {
                        logger.Info($"User {user.UserId}, feed {feedInfo.Url}: Feed didnt update");
                        continue;
                    }
                }
                else
                {
                    prevPubDate = DateTime.MinValue;
                }

                logger.Info($"User {user.UserId}, feed {feedInfo.Url}: Feed did update, new pub date: {feedData.LastBuildDate}");

                rssPubDates.Data.PubDates[feedInfo.Url] = feedData.LastBuildDate;

                foreach (var item in feedData.Items)
                {
                    if (item.PublicationDate <= prevPubDate && prevPubDate != DateTime.MinValue)
                    {
                        continue; // skipping the old item
                    }

                    logger.Info($"User {user.UserId}, feed {feedInfo.Url}: new feed item: {item.Title}, {item.Link}");

                    if (rssPubDates.Data.IsRecent(item.Link))
                    {
                        logger.Info($"User {user.UserId}, feed {feedInfo.Url}: user has seen this recently, skipping: {item.Link}");
                        continue;
                    }

                    bool hasKeywords = feedInfo.Keywords.Length == 0;

                    foreach (var kw in feedInfo.Keywords)
                    {
                        if (item.Title.Contains(kw, StringComparison.InvariantCultureIgnoreCase))
                        {
                            hasKeywords = true;
                            break;
                        }
                        else if (item.Description.Contains(kw, StringComparison.InvariantCultureIgnoreCase))
                        {
                            hasKeywords = true;
                            break;
                        }
                    }

                    if (hasKeywords)
                    {
                        if (rssPubDates.Data.IsRecentNotification(item.Title, item.Description))
                        {
                            logger.Info($"User {user.UserId}, feed {feedInfo.Url}: user has seen this recently, skipping: {item.Link} - skipped by the notification content that was sent today");
                            continue;
                        }

                        rssPubDates.Data.AddRecentLink(item.Link);
                        rssPubDates.Data.AddRecentNotification(item.Title, item.Description);

                        await SendRssItem(user, item, isMuted);
                    }
                }
            }

            rssPubDates.Save();
        }
Beispiel #12
0
        private async Task HandleAuthenticatedUserWordsCommand(
            ITelegramBotApi api,
            Update update,
            User from,
            Chat chat,
            long userId,
            string[] parsedCommand
            )
        {
            UnStop(userId);

            if (parsedCommand.Length < 2)
            {
                var rr = await api.RespondToUpdate(update, $"{from.FirstName}, please give arguments to the command");

                return;
            }

            var state = UserState <UserRssSubscriptions> .LoadOrDefault(userId);

            if (int.TryParse(parsedCommand[1], out var idx))
            {
                if (state.Data.RssEntries == null || idx >= state.Data.RssEntries.Count || idx < 0)
                {
                    var rr = await api.RespondToUpdate(update, $"{from.FirstName}, index {idx} is not known");

                    return;
                }

                var keyWords = parsedCommand.Skip(2).Select(x => ParseKeyword(x)).ToHashSet();
                state.Data.RssEntries[idx].Keywords = keyWords.ToArray();
                state.Save();

                var r = await api.RespondToUpdate(update, $"{from.FirstName}, {idx} was updated");
            }
            else if (parsedCommand[1] == "add" && parsedCommand.Length >= 4 &&
                     int.TryParse(parsedCommand[2], out var addIdx))
            {
                var addWords = parsedCommand.Select(x => ParseKeyword(x)).Skip(3);

                if (state.Data.RssEntries == null || addIdx >= state.Data.RssEntries.Count || addIdx < 0)
                {
                    var rr = await api.RespondToUpdate(update, $"{from.FirstName}, index {addIdx} is not known");

                    return;
                }

                if (state.Data.RssEntries[idx].Keywords == null)
                {
                    state.Data.RssEntries[idx].Keywords = addWords.ToArray();
                }
                else
                {
                    var words = state.Data.RssEntries[idx].Keywords.ToHashSet();
                    foreach (var newWord in addWords)
                    {
                        words.Add(newWord);
                    }
                    state.Data.RssEntries[idx].Keywords = words.ToArray();
                }

                state.Save();

                var r = await api.RespondToUpdate(update, $"{from.FirstName}, {idx} was updated");
            }
            else if (parsedCommand[1] == "del" && parsedCommand.Length >= 4 &&
                     int.TryParse(parsedCommand[2], out var delIdx))
            {
                var delWords = parsedCommand.Select(x => ParseKeyword(x)).Skip(3);

                if (state.Data.RssEntries == null || delIdx >= state.Data.RssEntries.Count || delIdx < 0)
                {
                    var rr = await api.RespondToUpdate(update, $"{from.FirstName}, index {delIdx} is not known");

                    return;
                }

                if (state.Data.RssEntries[idx].Keywords != null)
                {
                    var words = state.Data.RssEntries[idx].Keywords.ToHashSet();
                    foreach (var delWord in delWords)
                    {
                        words.Remove(delWord);
                    }
                    state.Data.RssEntries[idx].Keywords = words.ToArray();
                }

                state.Save();

                var note = (state.Data.RssEntries[idx].Keywords == null ||
                            state.Data.RssEntries[idx].Keywords.Length == 0)
                        ? ", WARNING: keyword list is not empty"
                        : "";

                var r = await api.RespondToUpdate(update, $"{from.FirstName}, {idx} was updated{note}");
            }
            else
            {
                var rr = await api.RespondToUpdate(update, $"{from.FirstName}, please give arguments to the command");

                return;
            }
        }
Beispiel #13
0
        private async Task HandleAuthenticatedUserAddCommand(
            ITelegramBotApi api,
            Update update,
            User from,
            Chat chat,
            long userId,
            string[] parsedCommand
            )
        {
            UnStop(userId);

            if (parsedCommand.Length < 2)
            {
                var rr = await api.RespondToUpdate(update, $"{from.FirstName}, please give arguments to the command");

                return;
            }

            var state = UserState <UserRssSubscriptions> .LoadOrDefault(userId);

            if (state.Data.RssEntries == null)
            {
                state.Data.RssEntries = new List <RssUrlEntry>();
            }

            var url       = parsedCommand[1];
            var keyboards = parsedCommand.Skip(2).Select(x => ParseKeyword(x)).ToArray();

            if (state.Data.RssEntries.Find(x => x.Url == url) != null)
            {
                var re = await api.RespondToUpdate(update, $"{from.FirstName}, the URI {url} is already in your list");

                return;
            }

            var rssParsed = await _rssReader.FetchAndParse(url);

            if (rssParsed == null)
            {
                var re = await api.RespondToUpdate(update, $"{from.FirstName}, the URI {url} is not looking like a valid RSS");

                return;
            }

            state.Data.RssEntries.Add(new RssUrlEntry {
                Url = url, Keywords = keyboards
            });

            state.Save();

            var rssPubDates = UserState <UserFeedPubDates> .LoadOrDefault(userId);

            if (rssPubDates.Data.PubDates == null)
            {
                rssPubDates.Data.PubDates = new SerializableDictionary <string, DateTime>();
            }
            rssPubDates.Data.PubDates[url] = rssParsed.LastBuildDate;

            try
            {
                rssPubDates.Save();
            }
            catch (Exception ex)
            {
                logger.Error(ex, "Exception while saving xml");
            }

            var r = await api.RespondToUpdate(update, $"{from.FirstName}, it was added");
        }