예제 #1
0
class RobotRss(object):
    def __init__(self, telegram_token, update_interval):

        # Initialize bot internals
        self.db = DatabaseHandler("resources/datastore.db")
        self.fh = FileHandler("..")

        # Register webhook to telegram bot
        self.updater = Updater(telegram_token)
        self.dispatcher = self.updater.dispatcher

        # Add Commands to bot
        self._addCommand(CommandHandler("start", self.start))
        self._addCommand(CommandHandler("stop", self.stop))
        self._addCommand(CommandHandler("help", self.help))
        self._addCommand(CommandHandler("list", self.list))
        self._addCommand(CommandHandler("add", self.add, pass_args=True))
        self._addCommand(CommandHandler("get", self.get, pass_args=True))
        self._addCommand(CommandHandler("remove", self.remove, pass_args=True))

        # Start the Bot
        self.processing = BatchProcess(database=self.db,
                                       update_interval=update_interval,
                                       bot=self.dispatcher.bot)

        self.processing.start()
        self.updater.start_polling()
        self.updater.idle()

    def _addCommand(self, command):
        """
        Registers a new command to the bot
        """

        self.updater.dispatcher.add_handler(command)

    def start(self, bot, update):
        """
        Send a message when the command /start is issued.
        """

        telegram_user = update.message.from_user

        # Add new User if not exists
        if not self.db.get_user(telegram_id=telegram_user.id):

            message = "Hello! I don't think we've met before! I am an RSS News Bot and would like to help you to receive your favourite news in the future! Let me first set up a few things before we start..."
            update.message.reply_text(message)

            self.db.add_user(telegram_id=telegram_user.id,
                             username=telegram_user.username,
                             firstname=telegram_user.first_name,
                             lastname=telegram_user.last_name,
                             language_code=telegram_user.language_code,
                             is_bot=telegram_user.is_bot,
                             is_active=1)

        self.db.update_user(telegram_id=telegram_user.id, is_active=1)

        message = "You will now receive news! Use /help if you need some tips how to tell me what to do!"
        update.message.reply_text(message)

    def add(self, bot, update, args):
        """
        Adds a rss subscription to user
        """

        telegram_user = update.message.from_user

        if len(args) != 2:
            message = "Sorry! I could not add the entry! Please use the the command passing the following arguments:\n\n /add <url> <entryname> \n\n Here is a short example: \n\n /add http://www.feedforall.com/sample.xml ExampleEntry"
            update.message.reply_text(message)
            return

        arg_url = FeedHandler.format_url_string(string=args[0])
        arg_entry = args[1]

        # Check if argument matches url format
        if not FeedHandler.is_parsable(url=arg_url):
            message = "Sorry! It seems like '" + \
                str(arg_url) + "' doesn't provide an RSS news feed.. Have you tried another URL from that provider?"
            update.message.reply_text(message)
            return

        # Check if entry does not exists
        entries = self.db.get_urls_for_user(telegram_id=telegram_user.id)
        print(entries)

        if any(arg_url.lower() in entry for entry in entries):
            message = "Sorry, " + telegram_user.first_name + \
                "! I already have that url with stored in your subscriptions."
            update.message.reply_text(message)
            return

        if any(arg_entry in entry for entry in entries):
            message = "Sorry! I already have an entry with name " + \
                arg_entry + " stored in your subscriptions.. Please choose another entry name or delete the entry using '/remove " + arg_entry + "'"
            update.message.reply_text(message)
            return

        self.db.add_user_bookmark(telegram_id=telegram_user.id,
                                  url=arg_url.lower(),
                                  alias=arg_entry)
        message = "I successfully added " + arg_entry + " to your subscriptions!"
        update.message.reply_text(message)

    def get(self, bot, update, args):
        """
        Manually parses an rss feed
        """

        telegram_user = update.message.from_user

        if len(args) > 2:
            message = "To get the last news of your subscription please use /get <entryname> [optional: <count 1-10>]. Make sure you first add a feed using the /add command."
            update.message.reply_text(message)
            return

        if len(args) == 2:
            args_entry = args[0]
            args_count = int(args[1])
        else:
            args_entry = args[0]
            args_count = 4

        url = self.db.get_user_bookmark(telegram_id=telegram_user.id,
                                        alias=args_entry)

        if url is None:
            message = "I can not find an entry with label " + \
                args_entry + " in your subscriptions! Please check your subscriptions using /list and use the delete command again!"
            update.message.reply_text(message)
            return

        entries = FeedHandler.parse_feed(url[0], args_count)
        for entry in entries:
            message = "[" + url[1] + "] <a href='" + \
                entry.link + "'>" + entry.title + "</a>"
            print(message)

            try:
                update.message.reply_text(message, parse_mode=ParseMode.HTML)
            except Unauthorized:
                self.db.update_user(telegram_id=telegram_user.id, is_active=0)
            except TelegramError:
                # handle all other telegram related errors
                pass

    def remove(self, bot, update, args):
        """
        Removes an rss subscription from user
        """

        telegram_user = update.message.from_user

        if len(args) != 1:
            message = "To remove a subscriptions from your list please use /remove <entryname>. To see all your subscriptions along with their entry names use /list !"
            update.message.reply_text(message)
            return

        entry = self.db.get_user_bookmark(telegram_id=telegram_user.id,
                                          alias=args[0])

        if entry:
            self.db.remove_user_bookmark(telegram_id=telegram_user.id,
                                         url=entry[0])
            message = "I removed " + args[0] + " from your subscriptions!"
            update.message.reply_text(message)
        else:
            message = "I can not find an entry with label " + \
                args[0] + " in your subscriptions! Please check your subscriptions using /list and use the delete command again!"
            update.message.reply_text(message)

    def list(self, bot, update):
        """
        Displays a list of all user subscriptions
        """

        telegram_user = update.message.from_user

        message = "Here is a list of all subscriptions I stored for you!"
        update.message.reply_text(message)

        entries = self.db.get_urls_for_user(telegram_id=telegram_user.id)

        for entry in entries:
            message = "[" + entry[1] + "]\n " + entry[0]
            update.message.reply_text(message)

    def help(self, bot, update):
        """
        Send a message when the command /help is issued.
        """

        message = "If you need help with handling the commands, please have a look at my <a href='https://github.com/serguk89/telegram-rss'>Github</a> page. There I have summarized everything necessary for you!"
        update.message.reply_text(message, parse_mode=ParseMode.HTML)

    def stop(self, bot, update):
        """
        Stops the bot from working
        """

        telegram_user = update.message.from_user
        self.db.update_user(telegram_id=telegram_user.id, is_active=0)

        message = "Oh.. Okay, I will not send you any more news updates! If you change your mind and you want to receive messages from me again use /start command again!"
        update.message.reply_text(message)
예제 #2
0
class RobotRss(object):

    def __init__(self, telegram_token, update_interval):

        # Initialize bot internals
        self.db = DatabaseHandler("resources/db.db")
        self.fh = FileHandler("..")

        # Register webhook to telegram bot
        self.updater = Updater(telegram_token)
        self.dispatcher = self.updater.dispatcher

        # Add Commands to bot
        self._addCommand(CommandHandler("start", self.start))
        self._addCommand(CommandHandler("stop", self.stop))
        self._addCommand(CommandHandler("help", self.help))
        self._addCommand(CommandHandler("list", self.list))
        self._addCommand(CommandHandler("about", self.about))
        self._addCommand(CommandHandler("add", self.add, pass_args=True))
        self._addCommand(CommandHandler("get", self.get, pass_args=True))
        self._addCommand(CommandHandler("remove", self.remove, pass_args=True))
        self._addCommand(CommandHandler("add_filter", self.add_filter, pass_args=True))


        # Start the Bot
        self.processing = BatchProcess(
            database=self.db, update_interval=update_interval, bot=self.dispatcher.bot)

        self.processing.start()
        self.updater.start_polling()
        self.updater.idle()

    def _addCommand(self, command):
        """
        Registers a new command to the bot
        """

        self.updater.dispatcher.add_handler(command)

    def start(self, bot, update):
        """
        Send a message when the command /start is issued.
        """

        telegram_user = update.message.from_user

        # Add new User if not exists
        if not self.db.get_user(telegram_id=telegram_user.id):

            message = "Hello! I don't think we've met before! I am an RSS News Bot and would like to help you to receive your favourite news in the future! Let me first set up a few things before we start..."
            update.message.reply_text(message)

            self.db.add_user(telegram_id=telegram_user.id,
                             username=telegram_user.username,
                             firstname=telegram_user.first_name,
                             lastname=telegram_user.last_name,
                             language_code=telegram_user.language_code,
                             is_bot=telegram_user.is_bot,
                             is_active=1)

        self.db.update_user(telegram_id=telegram_user.id, is_active=1)

        message = "You will now receive news! Use /help if you need some tips how to tell me what to do!"
        update.message.reply_text(message)

    def add(self, bot, update, args):
        """
        Adds a rss subscription to user
        """

        telegram_user = update.message.from_user

        if len(args) != 2:
            message = "Sorry! I could not add the entry! Please use the the command passing the following arguments:\n\n /add <url> <entryname> \n\n Here is a short example: \n\n /add http://www.feedforall.com/sample.xml ExampleEntry"
            update.message.reply_text(message)
            return

        arg_url = FeedHandler.format_url_string(string=args[0])
        arg_entry = args[1]

        # Check if argument matches url format
        if not FeedHandler.is_parsable(url=arg_url):
            message = "Sorry! It seems like '" + \
                str(arg_url) + "' doesn't provide an RSS news feed.. Have you tried another URL from that provider?"
            update.message.reply_text(message)
            return

        # Check if entry does not exists
        entries = self.db.get_urls_for_user(telegram_id=telegram_user.id)
        print(entries)

        if any(arg_url.lower() in entry for entry in entries):
            message = "Sorry, " + telegram_user.first_name + \
                "! I already have that url with stored in your subscriptions."
            update.message.reply_text(message)
            return

        if any(arg_entry in entry for entry in entries):
            message = "Sorry! I already have an entry with name " + \
                arg_entry + " stored in your subscriptions.. Please choose another entry name or delete the entry using '/remove " + arg_entry + "'"
            update.message.reply_text(message)
            return

        self.db.add_user_bookmark(
            telegram_id=telegram_user.id, url=arg_url.lower(), alias=arg_entry)
        message = "I successfully added " + arg_entry + " to your subscriptions!"
        update.message.reply_text(message)

    def get(self, bot, update, args):
        """
        Manually parses an rss feed
        """

        telegram_user = update.message.from_user

        if len(args) > 2:
            message = "To get the last news of your subscription please use /get <entryname> [optional: <count 1-10>]. Make sure you first add a feed using the /add command."
            update.message.reply_text(message)
            return

        if len(args) == 2:
            args_entry = args[0]
            args_count = int(args[1])
        else:
            args_entry = args[0]
            args_count = 4

        url = self.db.get_user_bookmark(
            telegram_id=telegram_user.id, alias=args_entry)

        if url is None:
            message = "I can not find an entry with label " + \
                args_entry + " in your subscriptions! Please check your subscriptions using /list and use the delete command again!"
            update.message.reply_text(message)
            return

        entries = FeedHandler.parse_feed(url[0], args_count)
        for entry in entries:
            message = "[" + url[1] + "] <a href='" + \
                entry.link + "'>" + entry.title + "</a>"
            print(message)

            try:
                update.message.reply_text(message, parse_mode=ParseMode.HTML)
            except Unauthorized:
                self.db.update_user(telegram_id=telegram_user.id, is_active=0)
            except TelegramError:
                # handle all other telegram related errors
                pass

    def remove(self, bot, update, args):
        """
        Removes an rss subscription from user
        """

        telegram_user = update.message.from_user

        if len(args) != 1:
            message = "To remove a subscriptions from your list please use /remove <entryname>. To see all your subscriptions along with their entry names use /list !"
            update.message.reply_text(message)
            return

        entry = self.db.get_user_bookmark(
            telegram_id=telegram_user.id, alias=args[0])

        if entry:
            self.db.remove_user_bookmark(
                telegram_id=telegram_user.id, url=entry[0])
            message = "I removed " + args[0] + " from your subscriptions!"
            update.message.reply_text(message)
        else:
            message = "I can not find an entry with label " + \
                args[0] + " in your subscriptions! Please check your subscriptions using /list and use the delete command again!"
            update.message.reply_text(message)

    def list(self, bot, update):
        """
        Displays a list of all user subscriptions
        """

        telegram_user = update.message.from_user

        message = "Here is a list of all subscriptions I stored for you!"
        update.message.reply_text(message)

        entries = self.db.get_urls_for_user(telegram_id=telegram_user.id)

        for entry in entries:
            message = "[" + entry[1] + "]\n " + entry[0]
            update.message.reply_text(message)

    def help(self, bot, update):
        """
        Send a message when the command /help is issued.
        """

        message = ("Commands:\n\n"
                   "/start\nsubscribe to the bot\n\n"
                   "/stop\nunsubscribe from the bot\n\n"
                   "/add <url> <entryname>\n Add new rss subscription\n\n"
                   "/remove <entryname>\n Remove rss subscription\n\n"
                   "/list\nShow subscriptions\n\n"
                   "add_filter <entryname> <filtername> <filter>\n Add a new filter to the specified rss feed.")

        update.message.reply_text(message, parse_mode=ParseMode.HTML)

    def stop(self, bot, update):
        """
        Stops the bot from working
        """

        telegram_user = update.message.from_user
        self.db.update_user(telegram_id=telegram_user.id, is_active=0)

        message = "Oh.. Okay, I will not send you any more news updates! If you change your mind and you want to receive messages from me again use /start command again!"
        update.message.reply_text(message)

    def about(self, bot, update):
        """
        Shows about information
        """

        message = "Thank you for using <b>RobotRSS</b>! \n\n If you like the bot, please recommend it to others! \n\nDo you have problems, ideas or suggestions about what the bot should be able to do? Then contact my developer <a href='http://cbrgm.de'>@cbrgm</a> or create an issue on <a href='https://github.com/cbrgm/telegram-robot-rss'>Github</a>. There you will also find my source code, if you are interested in how I work!"
        update.message.reply_text(message, parse_mode=ParseMode.HTML)

    def add_filter(self, bot, update, args):
        '''
        add a filter to a rss subscription of a user
        '''

        telegram_user = update.message.from_user

        if len(args) < 3:
            message = "/add_filter <feed name> <filter name> <filter string>.\n\n The filter name should be a simple word that you can use to identify and delete the filter\n\n The filter string can be any regex. If the regex matches anywhere in the feed title or text the message will be forwarded."
            update.message.reply_text(message)
            return

        url_alias = args[0]
        filter_alias = args[1]
        filter_regexp = args[2]
        #check if the regexp is multi-word
        if len(args) > 3:
            for i in range(3, len(args)):
                filter_regexp = filter_regexp + " " + args[i]


        entry = self.db.get_filter(telegram_user, filter_alias, url_alias)

        if entry:
            update.message.reply_text("Filter already exists")
        else:
            self.db.add_filter(telegram_user, filter_alias, filter_regexp, url_alias)
            update.message.reply_text("Added Filter %s to feed %s" % (filter_regexp, url_alias))
예제 #3
0
class TestDatabaseHandler(unittest.TestCase):

    def setUp(self):
        self.db = DatabaseHandler("resources/test.db")

    def test_add_user(self):
        self.db.add_user(telegram_id=25525, username="******",
                         firstname="John", lastname="Snow", language_code="DE", is_bot=False, is_active=True)
        result = self.db.get_user(telegram_id=25525)

        self.assertEqual(result[0], 25525)
        self.assertEqual(result[1], "TestDummy")
        self.assertEqual(result[2], "John")
        self.assertEqual(result[3], "Snow")
        self.assertEqual(result[4], "DE")
        self.assertFalse(result[5])
        self.assertTrue(result[6])

    def test_remove_user(self):
        self.db.add_user(telegram_id=25525, username="******",
                         firstname="John", lastname="Snow", language_code="DE", is_bot=False, is_active=True)
        self.db.remove_user(telegram_id=25525)
        result = self.db.get_user(telegram_id=25525)
        self.assertIsNone(result)

    def test_update_user(self):
        self.db.add_user(telegram_id=25525, username="******",
                         firstname="John", lastname="Snow", language_code="DE", is_bot=False, is_active=True)
        self.db.update_user(telegram_id=25525,
                            firstname="Jonathan", is_bot=True)
        result = self.db.get_user(telegram_id=25525)
        self.assertEqual(result[0], 25525)
        self.assertEqual(result[1], "TestDummy")
        self.assertEqual(result[2], "Jonathan")
        self.assertEqual(result[3], "Snow")
        self.assertEqual(result[4], "DE")
        self.assertTrue(result[5])

    def test_get_user(self):
        self.db.add_user(telegram_id=25525, username="******",
                         firstname="John", lastname="Snow", language_code="DE", is_bot=False, is_active=True)
        result = self.db.get_user(telegram_id=25525)

        self.assertEqual(result[0], 25525)
        self.assertEqual(result[1], "TestDummy")
        self.assertEqual(result[2], "John")
        self.assertEqual(result[3], "Snow")
        self.assertEqual(result[4], "DE")
        self.assertFalse(result[5])

    def test_add_url(self):
        self.db.add_url(url="https://lorem-rss.herokuapp.com/feed")
        result = self.db.get_url(url="https://lorem-rss.herokuapp.com/feed")

        self.assertEqual(result[0], "https://lorem-rss.herokuapp.com/feed")

    def test_remove_url(self):
        self.db.add_url(url="https://lorem-rss.herokuapp.com/feed")
        self.db.remove_url(url="https://lorem-rss.herokuapp.com/feed")
        result = self.db.get_url(url="https://lorem-rss.herokuapp.com/feed")
        self.assertIsNone(result)

    def test_remove_url_has_references(self):
        self.db.add_url(url="https://lorem-rss.herokuapp.com/feed")

        self.db.add_user(telegram_id=25525, username="******",
                         firstname="John", lastname="Snow", language_code="DE", is_bot=False, is_active=True)
        self.db.add_user(telegram_id=25526, username="******",
                         firstname="John", lastname="Snow", language_code="DE", is_bot=False, is_active=True)

        self.db.add_user_bookmark(
            telegram_id=25525, url="https://lorem-rss.herokuapp.com/feed", alias="Test")
        self.db.add_user_bookmark(
            telegram_id=25525, url="https://lorem-rss.herokuapp.com/feed", alias="TestEntry")

        self.db.remove_url(url="https://lorem-rss.herokuapp.com/feed")

        result = self.db.get_users_for_url(
            url="https://lorem-rss.herokuapp.com/feed")
        self.assertEqual(len(result), 0)

        result = self.db.get_url(url="https://lorem-rss.herokuapp.com/feed")
        self.assertIsNone(result)

    def test_update_url(self):
        self.db.add_url(url="https://lorem-rss.herokuapp.com/feed")
        entry = self.db.get_url(url="https://lorem-rss.herokuapp.com/feed")

        timestamp = str(dh.get_datetime_now())

        self.db.update_url(
            url="https://lorem-rss.herokuapp.com/feed", last_updated=timestamp)
        result = self.db.get_url(url="https://lorem-rss.herokuapp.com/feed")
        self.assertEqual(result[1], timestamp)

    def test_get_url(self):
        self.db.add_url(url="https://lorem-rss.herokuapp.com/feed")
        result = self.db.get_url(url="https://lorem-rss.herokuapp.com/feed")

        self.assertEqual(result[0], "https://lorem-rss.herokuapp.com/feed")

    def test_add_user_bookmark(self):
        self.db.add_user(telegram_id=25525, username="******",
                         firstname="John", lastname="Snow", language_code="DE", is_bot=False, is_active=True)

        self.db.add_user_bookmark(
            telegram_id=25525, url="https://lorem-rss.herokuapp.com/feed01", alias="feed01")
        self.db.add_user_bookmark(
            telegram_id=25525, url="https://lorem-rss.herokuapp.com/feed02", alias="feed02")
        self.db.add_user_bookmark(
            telegram_id=25525, url="https://lorem-rss.herokuapp.com/feed03", alias="feed03")

        result = self.db.get_urls_for_user(telegram_id=25525)

        self.assertEqual(len(result), 3)
        self.assertEqual(
            result[0][0], "https://lorem-rss.herokuapp.com/feed01")
        self.assertEqual(
            result[1][0], "https://lorem-rss.herokuapp.com/feed02")
        self.assertEqual(
            result[2][0], "https://lorem-rss.herokuapp.com/feed03")

    def test_remove_bookmark(self):
        self.db.add_user(telegram_id=25525, username="******",
                         firstname="John", lastname="Snow", language_code="DE", is_bot=False, is_active=True)

        self.db.add_user_bookmark(
            telegram_id=25525, url="https://lorem-rss.herokuapp.com/feed01", alias="feed")

        self.db.remove_user_bookmark(
            telegram_id=25525, url="https://lorem-rss.herokuapp.com/feed01")
        result = self.db.get_urls_for_user(telegram_id=25525)
        self.assertEqual(len(result), 0)

    def test_update_bookmark(self):
        pass

    def test_get_urls_for_user(self):
        self.db.add_user(telegram_id=25525, username="******",
                         firstname="John", lastname="Snow", language_code="DE", is_bot=False, is_active=True)

        self.db.add_user_bookmark(
            telegram_id=25525, url="https://lorem-rss.herokuapp.com/feed01", alias="feed01")
        self.db.add_user_bookmark(
            telegram_id=25525, url="https://lorem-rss.herokuapp.com/feed02", alias="feed02")
        self.db.add_user_bookmark(
            telegram_id=25525, url="https://lorem-rss.herokuapp.com/feed03", alias="feed03")

        result = self.db.get_urls_for_user(telegram_id=25525)

        self.assertEqual(len(result), 3)
        self.assertEqual(
            result[0][0], "https://lorem-rss.herokuapp.com/feed01")
        self.assertEqual(
            result[1][0], "https://lorem-rss.herokuapp.com/feed02")
        self.assertEqual(
            result[2][0], "https://lorem-rss.herokuapp.com/feed03")

    def test_get_users_for_url(self):
        self.db.add_user(telegram_id=25526, username="******",
                         firstname="John", lastname="Snow", language_code="DE", is_bot=False, is_active=True)
        self.db.add_user(telegram_id=25527, username="******",
                         firstname="John", lastname="Snow", language_code="DE", is_bot=False, is_active=True)
        self.db.add_user(telegram_id=25528, username="******",
                         firstname="John", lastname="Snow", language_code="DE", is_bot=False, is_active=True)

        self.db.add_user_bookmark(
            telegram_id=25526, url="http://cbrgm.de", alias="cbrgm")
        self.db.add_user_bookmark(
            telegram_id=25527, url="http://cbrgm.de", alias="niceblog")
        self.db.add_user_bookmark(
            telegram_id=25528, url="http://cbrgm.de", alias="awesome")

        result = self.db.get_users_for_url("http://cbrgm.de")

        self.assertEqual(len(result), 3)
        self.assertEqual(result[0][1], "TestDummy01")
        self.assertEqual(result[1][1], "TestDummy02")
        self.assertEqual(result[2][1], "TestDummy03")

    def test_get_user_bookmark(self):
        self.db.add_user(telegram_id=25525, username="******",
                         firstname="John", lastname="Snow", language_code="DE", is_bot=False, is_active=True)
        self.db.add_user_bookmark(
            url="https://lorem-rss.herokuapp.com/feed", telegram_id=25525, alias="Test")

        bookmark = self.db.get_user_bookmark(telegram_id=25525, alias="Test")
        self.assertEqual(bookmark[0], "https://lorem-rss.herokuapp.com/feed")
        self.assertEqual(bookmark[1], "Test")

    def test_remove_if_not_referenced(self):
        self.db.add_url(url="https://lorem-rss.herokuapp.com/feed")
        self.db.add_user(telegram_id=25525, username="******",
                         firstname="John", lastname="Snow", language_code="DE", is_bot=False, is_active=True)

        self.db.add_user_bookmark(
            url="https://lorem-rss.herokuapp.com/feed", telegram_id=25525, alias="Test")

        self.db.remove_user_bookmark(
            telegram_id=25525, url="https://lorem-rss.herokuapp.com/feed")

        web = self.db.get_url("https://lorem-rss.herokuapp.com/feed")
        self.assertIsNone(web)

    def test_dont_remove_if_referenced(self):
        self.db.add_url(url="https://lorem-rss.herokuapp.com/feed")
        self.db.add_user(telegram_id=25525, username="******",
                         firstname="John", lastname="Snow", language_code="DE", is_bot=False, is_active=True)
        self.db.add_user(telegram_id=25526, username="******",
                         firstname="John", lastname="Snow", language_code="DE", is_bot=False, is_active=True)
        self.db.add_user_bookmark(
            url="https://lorem-rss.herokuapp.com/feed", telegram_id=25525, alias="Test")
        self.db.add_user_bookmark(
            url="https://lorem-rss.herokuapp.com/feed", telegram_id=25526, alias="MyTest")

        self.db.remove_user_bookmark(
            telegram_id=25525, url="https://lorem-rss.herokuapp.com/feed")

        web = self.db.get_url("https://lorem-rss.herokuapp.com/feed")
        self.assertEqual(web[0], "https://lorem-rss.herokuapp.com/feed")

    def tearDown(self):
        base_path = os.path.abspath(os.path.dirname(__file__))
        filepath = os.path.join(base_path, '..', "resources/test.db")
        os.remove(filepath)
예제 #4
0
class RobotRss(object):
    def __init__(self, telegram_token, update_interval):

        # Initialize bot internals
        self.db = DatabaseHandler("resources/userdata/datastore.db")
        self.fh = FileHandler("..")
        self.inventory = InventoryHandler()

        # Register webhook to telegram bot
        self.updater = Updater(telegram_token)
        self.dispatcher = self.updater.dispatcher

        # Add Commands to bot
        self._addCommand(CommandHandler("start", self.start))
        self._addCommand(CommandHandler("stop", self.stop))
        self._addCommand(CommandHandler("help", self.help))
        self._addCommand(CommandHandler("list", self.list))
        self._addCommand(CommandHandler("about", self.about))
        self._addCommand(CommandHandler("add", self.add, pass_args=True))
        self._addCommand(CommandHandler("get", self.get, pass_args=True))
        self._addCommand(CommandHandler("remove", self.remove, pass_args=True))
        self._addCommand(
            CommandHandler("addgroup", self.add_group, pass_args=True))
        self._addCommand(
            CommandHandler("search", self.inventory_search, pass_args=True))
        self._addCommand(MessageHandler(Filters.text, self.vechten))
        self._addCommand(MessageHandler(Filters.command, self.unknown))
        self._addCommand(InlineQueryHandler(self.inlinequery))
        # Start the Bot
        self.processing = BatchProcess(database=self.db,
                                       update_interval=update_interval,
                                       bot=self.dispatcher.bot)

        self.processing.start()
        self.updater.start_polling()
        self.updater.idle()

    def _addCommand(self, command):
        """
        Registers a new command to the bot
        """

        self.updater.dispatcher.add_handler(command)

    def inlinequery(self, bot, update):
        query = update.inline_query.query
        print(query)
        searchresults = self.inventory.search_many(query)
        print(searchresults)
        queryresults = []
        for result in searchresults:
            queryresult = InlineQueryResultPhoto(
                id=uuid4(),
                title=result[0],
                description=result[1],
                caption=
                "<b>Voorwerp</b>: {}\n<b>Omschrijving:</b> {}\n<b>Locatie:</b> {}"
                .format(result[0], result[1], result[2]),
                parse_mode="HTML",
                photo_url=result[3],
                thumb_url=result[3])
            queryresults.append(queryresult)

        update.inline_query.answer(queryresults)

    def start(self, bot, update):
        """
        Send a message when the command /start is issued.
        """

        telegram_user = update.message.from_user

        # Add new User if not exists
        if not self.db.get_user(telegram_id=telegram_user.id):
            message = "Hee, jou ken ik nog niet.. Ik stop je ff in mijn database, momentje."
            update.message.reply_text(message)

            self.db.add_user(telegram_id=telegram_user.id,
                             username=telegram_user.username,
                             firstname=telegram_user.first_name,
                             lastname=telegram_user.last_name,
                             language_code=telegram_user.language_code,
                             is_bot=telegram_user.is_bot,
                             is_active=1)

        self.db.update_user(telegram_id=telegram_user.id, is_active=1)

        message = "Je krijgt nu persoonlijk nieuws. Tik /help voor de commando's"
        update.message.reply_text(message)

    def add(self, bot, update, args):
        """
        Adds a rss subscription to user
        """

        telegram_user = update.message.from_user

        if len(args) != 2:
            message = "Ja, daar snap dus ik dus niks van. Probeer dit eens:\n" \
                      " /add <url> <naampje>"
            update.message.reply_text(message)
            return

        arg_url = FeedHandler.format_url_string(string=args[0])
        arg_entry = args[1]

        # Check if argument matches url format
        if not FeedHandler.is_parsable(url=arg_url):
            message = "Die url lijkt niet helemaal lekker!"
            update.message.reply_text(message)
            return

        # Check if entry does not exists
        entries = self.db.get_urls_for_user(telegram_id=telegram_user.id)

        if any(arg_url.lower() in entry for entry in entries):
            message = "Deze url heb je al toegevoegd!"
            update.message.reply_text(message)
            return

        if any(arg_entry in entry for entry in entries):
            message = "Je hebt hetzelfde naampje gebruikt als een andere url, da ga nie"
            update.message.reply_text(message)
            return

        self.db.add_user_bookmark(telegram_id=telegram_user.id,
                                  url=arg_url.lower(),
                                  alias=arg_entry)
        message = "Hij staat erbij! Gebruik /list als je me niet gelooft"
        update.message.reply_text(message)

    def get(self, bot, update, args):
        """
        Manually parses an rss feed
        """

        telegram_user = update.message.from_user

        if len(args) > 2:
            message = "To get the last news of your subscription please use /get <entryname> [optional: <count 1-10>]. Make sure you first add a feed using the /add command."
            update.message.reply_text(message)
            return

        if len(args) == 2:
            args_entry = args[0]
            args_count = int(args[1])
        else:
            args_entry = args[0]
            args_count = 4

        url = self.db.get_user_bookmark(telegram_id=telegram_user.id,
                                        alias=args_entry)

        if url is None:
            message = "I can not find an entry with label " + \
                      args_entry + " in your subscriptions! Please check your subscriptions using /list and use the delete command again!"
            update.message.reply_text(message)
            return

        entries = FeedHandler.parse_feed(url[0], args_count)
        for entry in entries:
            message = "[" + url[1] + "] <a href='" + \
                      entry.link + "'>" + entry.title + "</a>"
            print(message)

            try:
                update.message.reply_text(message, parse_mode=ParseMode.HTML)
            except Unauthorized:
                self.db.update_user(telegram_id=telegram_user.id, is_active=0)
            except TelegramError as e:
                # handle all other telegram related errors
                print("Telegram error: {0}".format(e.message))
                pass

    def remove(self, bot, update, args):
        """
        Removes an rss subscription from user
        """

        telegram_user = update.message.from_user

        if len(args) != 1:
            message = "To remove a subscriptions from your list please use /remove <entryname>. " \
                      "To see all your subscriptions along with their entry names use /list !"
            update.message.reply_text(message)
            return

        entry = self.db.get_user_bookmark(telegram_id=telegram_user.id,
                                          alias=args[0])

        if entry:
            self.db.remove_user_bookmark(telegram_id=telegram_user.id,
                                         url=entry[0])
            message = "I removed " + args[0] + " from your subscriptions!"
            update.message.reply_text(message)
        else:
            message = "I can not find an entry with label " + \
                      args[
                          0] + " in your subscriptions! Please check your subscriptions using /list and use the delete command again!"
            update.message.reply_text(message)

    def list(self, bot, update):
        """
        Displays a list of all user subscriptions
        """

        telegram_user = update.message.from_user

        message = "Hier is het lijstje met url's en groepen/users:"
        update.message.reply_text(message)

        # Group URL's
        entries = self.db.get_channels()
        for entry in entries:
            message = "[" + entry[0] + "]\n " + entry[1]
            update.message.reply_text(message)

        # User URL's
        entries = self.db.get_urls_for_user(telegram_id=telegram_user.id)
        for entry in entries:
            message = "[" + entry[1] + "]\n " + entry[0]
            update.message.reply_text(message)

    def help(self, bot, update):
        """
        Send a message when the command /help is issued.
        """

        message = "Ik snap de volgende commando's:\n" \
                  "/help: Deze helptekst\n" \
                  "/about: Info over deze bot\n" \
                  "/start: Zet het sturen van nieuwsupdates aan\n" \
                  "/stop: Stop met sturen van nieuwsupdates\n" \
                  "/list: Geef een lijst van feeds\n" \
                  "/add <url> <naam>: Voeg een nieuwe feed toe\n" \
                  "/addgroup <url> <@grouphandle>\n" \
                  "/search <keyword>: Zoek in de DJO inventaris"
        update.message.reply_text(message)

    def stop(self, bot, update):
        """
        Stops the bot from working
        """

        telegram_user = update.message.from_user
        self.db.update_user(telegram_id=telegram_user.id, is_active=0)

        message = "Jahaaa, ik stop al."
        update.message.reply_text(message)

    def about(self, bot, update):
        """
        Shows about information
        """

        message = "Dit is de officiele DJO Amersfoort Telegram Bot. Hier staat mijn source: " \
                  " <a href='https://github.com/djoamersfoort/djo-telegram-bot'>Github</a>."
        update.message.reply_text(message, parse_mode=ParseMode.HTML)

    def add_group(self, bot, update, args):
        if len(args) != 2:
            message = "Ja, daar snap ik dus helemaal niks van. Probeer dit eens:\n" \
                      "/addgroup <url> <groupame>"
            update.message.reply_text(message)
            return

        arg_url = FeedHandler.format_url_string(string=args[0])
        arg_channel = args[1]

        # Check if argument matches url format
        if not FeedHandler.is_parsable(url=arg_url):
            message = "Die url lijkt niet helemaal lekker!"
            update.message.reply_text(message)
            return

        if not arg_channel.startswith('@'):
            message = "Een groepnaam moet met @ starten"
            update.message.reply_text(message)
            return

        channels = self.db.get_channels()
        if any(channel[0] == arg_channel and channel[1] == arg_url
               for channel in channels):
            update.message.reply_text(
                "Deze url is al aanwezig voor deze groep!")
            return

        # Add the channel + url
        self.db.add_url(arg_url)
        self.db.add_channel(arg_channel, arg_url)
        message = "Channel en url zijn toegevoegd!"
        update.message.reply_text(message)

    def inventory_search(self, bot, update, args):
        if not len(args) >= 1:
            update.message.reply_text('Waar wil je naar zoeken?')
            return

        keyword = ' '.join(args[0:])
        (text, image) = self.inventory.search(keyword)
        if image is not None:
            update.message.reply_photo(image,
                                       quote=False,
                                       caption=text,
                                       parse_mode=ParseMode.HTML)
        else:
            update.message.reply_text(text,
                                      quote=False,
                                      parse_mode=ParseMode.HTML)

    def vechten(self, bot, update):
        if "kom vechten" in update.message.text.lower():
            print("Iemand wil vechten")
            update.message.reply_document(
                'https://i.kym-cdn.com/photos/images/original/001/356/324/914.gif'
            )

    def unknown(self, bot, update):
        message = "Computer says no"
        update.message.reply_text(message)
예제 #5
0
class RobotRss(object):

    def __init__(self, telegram_token, update_interval):

        # Initialize bot internals
        self.db = DatabaseHandler("resources/datastore.db")
        self.fh = FileHandler("..")

        # Register webhook to telegram bot
        self.updater = Updater(telegram_token)
        self.dispatcher = self.updater.dispatcher

        # Add Commands to bot
        self._addCommand(CommandHandler("start", self.start))
        self._addCommand(CommandHandler("stop", self.stop))
        self._addCommand(CommandHandler("help", self.help))
        self._addCommand(CommandHandler("list", self.list))
        self._addCommand(CommandHandler("about", self.about))
        self._addCommand(CommandHandler("add", self.add, pass_args=True))
        self._addCommand(CommandHandler("get", self.get, pass_args=True))
        self._addCommand(CommandHandler("remove", self.remove, pass_args=True))

        # Start the Bot
        self.processing = BatchProcess(
            database=self.db, update_interval=update_interval, bot=self.dispatcher.bot)

        self.processing.start()
        self.updater.start_polling()
        self.updater.idle()

    def _addCommand(self, command):
        """
        Registers a new command to the bot
        """

        self.updater.dispatcher.add_handler(command)

    def start(self, bot, update):
        """
        Send a message when the command /start is issued.
        """

        telegram_user = update.message.from_user

        # Add new User if not exists
        if not self.db.get_user(telegram_id=telegram_user.id):

            message = "Hello! I don't think we've met before! I am an RSS News Bot and would like to help you to receive your favourite news in the future! Let me first set up a few things before we start..."
            update.message.reply_text(message)

            self.db.add_user(telegram_id=telegram_user.id,
                             username=telegram_user.username,
                             firstname=telegram_user.first_name,
                             lastname=telegram_user.last_name,
                             language_code=telegram_user.language_code,
                             is_bot=telegram_user.is_bot,
                             is_active=1)

        self.db.update_user(telegram_id=telegram_user.id, is_active=1)

        message = "You will now receive news! Use /help if you need some tips how to tell me what to do!"
        update.message.reply_text(message)

    def add(self, bot, update, args):
        """
        Adds a rss subscription to user
        """

        telegram_user = update.message.from_user

        if len(args) != 2:
            message = "Sorry! I could not add the entry! Please use the the command passing the following arguments:\n\n /add <url> <entryname> \n\n Here is a short example: \n\n /add http://www.feedforall.com/sample.xml ExampleEntry"
            update.message.reply_text(message)
            return

        arg_url = args[0]
        arg_entry = args[1]

        # Check if argument matches url format
        feed=FeedHandler.is_parsable(url=arg_url)
        if not feed:
            message = f"Sorry! It seems like {arg_url}" + \
                "' doesn't provide an RSS news feed... Have you tried another URL from that provider?"
            update.message.reply_text(message)
            return

        # Check if entry does not exists
        entries = self.db.get_urls_for_user(telegram_id=telegram_user.id)
        if any(arg_url.lower() in entry.lower() for entry,_ in entries):
            message = f"Sorry, {telegram_user.first_name}" + \
                "! I already have that url stored in your subscriptions."
            update.message.reply_text(message)
            return

        if any(arg_entry in entry for entry in entries):
            message = f"Sorry! I already have an entry with name {arg_entry}" + \
                " stored in your subscriptions.. Please choose another entry name or delete the entry using '/remove {arg_entry}'"
            update.message.reply_text(message)
            return

        urls = self.db.get_all_urls()
        if not (arg_url in urls):
            items = {}
            for item in feed:
                for key in ['summary', 'title', 'link']:
                    if not(key in item.keys()):
                        item[key]=''
                hash=CityHash64(item['summary']+item['title']+item['link'])
                items[hash] = {'active': True, 'last_date': DateHandler.get_datetime_now()}
            self.db.add_url(url=arg_url, items=items)

        self.db.add_user_bookmark(telegram_id=telegram_user.id, url=arg_url, alias=arg_entry)
        message = f"I successfully added {arg_entry} to your subscriptions!"
        update.message.reply_text(message)

    def get(self, bot, update, args):
        """
        Manually parses an rss feed
        """

        telegram_user = update.message.from_user

        if len(args) > 2:
            message = "To get the last news of your subscription please use /get <entryname> [optional: <count 1-10>]. Make sure you first add a feed using the /add command."
            update.message.reply_text(message)
            return

        if len(args) == 2:
            args_entry = args[0]
            args_count = int(args[1])
        else:
            args_entry = args[0]
            args_count = 4

        if not(1 <= args_count <= 10):
            message = "Count parameter (if used) must be between 1 and 10.\n" + \
                "Usage: /get <entryname> [optional: <count 1-10>]"
            update.message.reply_text(message)
            return

        url = self.db.get_user_bookmark(telegram_id=telegram_user.id, alias=args_entry)

        if url is None:
            message = "I can not find an entry with label " + \
                args_entry + " in your subscriptions! Please check your subscriptions using /list and use the delete command again!"
            update.message.reply_text(message)
            return

        entries = FeedHandler.parse_feed(url[0], args_count)
        for entry in entries:
            message = f"[{url[1]}] <a href='{entry.link}'>{entry.title}</a>"
            print(message)

            try:
                update.message.reply_text(message, parse_mode=ParseMode.HTML)
            except Unauthorized:
                self.db.update_user(telegram_id=telegram_user.id, is_active=0)
            except TelegramError:
                # handle all other telegram related errors
                pass

    def remove(self, bot, update, args):
        """
        Removes an rss subscription from user
        """

        telegram_user = update.message.from_user

        if len(args) != 1:
            message = "To remove a subscriptions from your list please use /remove <entryname>. To see all your subscriptions along with their entry names use /list !"
            update.message.reply_text(message)
            return

        entry = self.db.get_user_bookmark(
            telegram_id=telegram_user.id, alias=args[0])

        if entry:
            self.db.remove_user_bookmark(
                telegram_id=telegram_user.id, url=entry[0])
            message = "I removed " + args[0] + " from your subscriptions!"
            update.message.reply_text(message)
        else:
            message = "I can not find an entry with label " + \
                args[0] + " in your subscriptions! Please check your subscriptions using /list and use the delete command again!"
            update.message.reply_text(message)

    def list(self, bot, update):
        """
        Displays a list of all user subscriptions
        """

        telegram_user = update.message.from_user

        message = "Here is a list of all subscriptions I stored for you!"
        update.message.reply_text(message)

        entries = self.db.get_urls_for_user(telegram_id=telegram_user.id)

        for entry in entries:
            message = f"[{entry[1]}]\n {entry[0]}"
            update.message.reply_text(message)

    def help(self, bot, update):
        """
        Send a message when the command /help is issued.
        """

        message = "If you need help with handling the commands, please have a look at my <a href='https://github.com/cbrgm/telegram-robot-rss'>Github</a> page. There I have summarized everything necessary for you!"
        update.message.reply_text(message, parse_mode=ParseMode.HTML)

    def stop(self, bot, update):
        """
        Stops the bot from working
        """

        telegram_user = update.message.from_user
        self.db.update_user(telegram_id=telegram_user.id, is_active=0)

        message = "Oh.. Okay, I will not send you any more news updates! If you change your mind and you want to receive messages from me again use /start command again!"
        update.message.reply_text(message)

    def about(self, bot, update):
        """
        Shows about information
        """

        message = "Thank you for using <b>RobotRSS</b>! \n\n If you like the bot, please recommend it to others! \n\nDo you have problems, ideas or suggestions about what the bot should be able to do? Then contact my developer <a href='http://cbrgm.de'>@cbrgm</a> or create an issue on <a href='https://github.com/cbrgm/telegram-robot-rss'>Github</a>. There you will also find my source code, if you are interested in how I work!"
        update.message.reply_text(message, parse_mode=ParseMode.HTML)