예제 #1
0
    def update_model_image(self):
        """
        Updates self.image


        :raise ModelOffline if self.status is 'offline'
        :raise ModelAway if self.status is 'away'
        :raise ModelPrivate if self.status is 'private' or 'hidden'
        :raise ModelPassword if self.status is 'password'
        :raise ModelDeleted if self.status is 'deleted'
        :raise ModelBanned if self.status is 'banned'
        :raise ModelGeoblocked if self.status is 'geoblocked'
        :raise ModelCanceled if self.status is 'canceled'
        :raise ModelNotViewable if any other error happens
        """
        if self.online and self.status not in {
                "away", "private", "hidden", "password"
        }:
            attempt_count = 0
            for attempt in range(5):
                try:
                    data = requests.get(
                        f'https://roomimg.stream.highwebmedia.com/ri/{self.username}.jpg'
                    ).content
                    bio_data = io.BytesIO(data)
                    self.model_image = bio_data
                except Exception as e:
                    Utils.handle_exception(e)
                    attempt_count += 1
                    logging.info(self.username +
                                 " has failed to obtain image on attempt " +
                                 str(attempt))
                    time.sleep(1)  # sleep and retry
                else:
                    break
            if attempt_count == 5:
                logging.info(self.username +
                             " has failed to obtain image after all attempts")
                raise ConnectionError
        elif self.status == "offline":
            raise Exceptions.ModelOffline
        elif self.status == "away":
            raise Exceptions.ModelAway
        elif self.status in {"private", "hidden"}:
            raise Exceptions.ModelPrivate
        elif self.status == "password":
            raise Exceptions.ModelPassword
        elif self.status == "deleted":
            raise Exceptions.ModelDeleted
        elif self.status == "banned":
            raise Exceptions.ModelBanned
        elif self.status == "geoblocked":
            raise Exceptions.ModelGeoblocked
        elif self.status == "canceled":
            raise Exceptions.ModelCanceled
        else:
            raise Exceptions.ModelNotViewable
예제 #2
0
def send_image(chatid: str, image, bot: updater.bot, html: bool = False, markup=None, caption=None) -> None:
    """
    Sends an image to a telegram user and sends "sending image" action


    :param chatid: The chatid of the user who will receive the message
    :param image: The image to send
    :param bot: telegram bot instance
    :param html: Enable html markdown parsing in the message
    :param markup: The reply_markup to use when sending the message
    """

    notification = not Preferences.get_user_notifications_sound_preference(
        chatid)  # the setting is opposite of preference

    try:
        bot.send_chat_action(chatid, action="upload_photo")
        if html and markup != None and caption != None:
            bot.send_photo(chat_id=chatid, photo=image, parse_mode=telegram.ParseMode.HTML, reply_markup=markup,
                           disable_notification=notification, caption=caption)
        elif html and markup != None:
            bot.send_photo(chat_id=chatid, photo=image, parse_mode=telegram.ParseMode.HTML, reply_markup=markup,
                           disable_notification=notification)
        elif markup != None and caption != None:
            bot.send_photo(chat_id=chatid, photo=image, reply_markup=markup, disable_notification=notification,
                           caption=caption)
        elif html and caption != None:
            bot.send_photo(chat_id=chatid, photo=image, parse_mode=telegram.ParseMode.HTML,
                           disable_notification=notification, caption=caption)
        elif html:
            bot.send_photo(chat_id=chatid, photo=image, parse_mode=telegram.ParseMode.HTML,
                           disable_notification=notification)
        elif markup != None:
            bot.send_photo(chat_id=chatid, photo=image, reply_markup=markup, disable_notification=notification)
        elif caption != None:
            bot.send_photo(chat_id=chatid, photo=image, disable_notification=notification, caption=caption)
        else:
            bot.send_photo(chat_id=chatid, photo=image, disable_notification=notification)
    except Unauthorized:  # user blocked the bot
        if auto_remove == True:
            logging.info(f"{chatid} blocked the bot, he's been removed from the database")
            Utils.exec_query(f"DELETE FROM CHATURBATE WHERE CHAT_ID='{chatid}'")
            Preferences.remove_user_from_preferences(chatid)
    except Exception as e:
        Utils.handle_exception(e)
예제 #3
0
def send_message(chatid: str, messaggio: str, bot: updater.bot, html: bool = False, markup=None) -> None:
    """
    Sends a message to a telegram user and sends "typing" action


    :param chatid: The chatid of the user who will receive the message
    :param messaggio: The message who the user will receive
    :param bot: telegram bot instance
    :param html: Enable html markdown parsing in the message
    :param markup: The reply_markup to use when sending the message
    """

    disable_webpage_preview = not Preferences.get_user_link_preview_preference(
        chatid)  # the setting is opposite of preference

    notification = not Preferences.get_user_notifications_sound_preference(
        chatid)  # the setting is opposite of preference

    try:
        bot.send_chat_action(chat_id=chatid, action="typing")
        if html and markup != None:
            bot.send_message(chat_id=chatid, text=messaggio,
                             parse_mode=telegram.ParseMode.HTML, disable_web_page_preview=disable_webpage_preview,
                             reply_markup=markup, disable_notification=notification)
        elif html:
            bot.send_message(chat_id=chatid, text=messaggio,
                             parse_mode=telegram.ParseMode.HTML, disable_web_page_preview=disable_webpage_preview,
                             disable_notification=notification)
        elif markup != None:
            bot.send_message(chat_id=chatid, text=messaggio, disable_web_page_preview=disable_webpage_preview,
                             reply_markup=markup, disable_notification=notification)
        else:
            bot.send_message(chat_id=chatid, text=messaggio, disable_web_page_preview=disable_webpage_preview,
                             disable_notification=notification)
    except Unauthorized:  # user blocked the bot
        if auto_remove == True:
            logging.info(f"{chatid} blocked the bot, he's been removed from the database")
            Utils.exec_query(f"DELETE FROM CHATURBATE WHERE CHAT_ID='{chatid}'")
            Preferences.remove_user_from_preferences(chatid)
    except Exception as e:
        Utils.handle_exception(e)
예제 #4
0
    def update_status() -> None:
        username_list = []
        chat_and_online_dict = {}

        # create a dictionary with usernames and online using distinct

        username_list = Utils.alchemy_instance.session.query(
            ChaturbateUser.username).distinct().all()

        # obtain chatid
        for username in username_list:
            results: List[
                ChaturbateUser] = Utils.alchemy_instance.session.query(
                    ChaturbateUser).filter_by(username=username).all()
            chat_and_online_dict[
                username] = results  # assign (chatid,online) to every model

        # Threaded function for queue processing.
        def crawl(q, model_instances_dict):
            while not q.empty():
                username = Utils.sanitize_username(q.get()[1].username)
                model_instance = Model(username, autoupdate=False)
                model_instance.update_model_status()
                try:
                    model_instance.update_model_image()
                except Exception:
                    model_instance.model_image = None  # set to None just to be secure Todo: this may be extra

                model_instances_dict[username] = model_instance
                # signal to the queue that task has been processed
                q.task_done()
            return True

        q = Queue(maxsize=0)
        # Populating Queue with tasks
        model_instances_dict = {}

        # load up the queue with the username_list to fetch and the index for each job (as a tuple):
        for index, value in enumerate(username_list):
            # need the index and the username in each queue item.
            q.put((index, value))

            # Starting worker threads on queue processing
        for i in range(http_threads):
            worker = threading.Thread(target=crawl,
                                      args=(q, model_instances_dict),
                                      daemon=True)
            worker.start()
            time.sleep(
                wait_time
            )  # avoid server spamming by time-limiting the start of requests

        # now we wait until the queue has been processed
        q.join()

        for username in username_list:
            model_instance = model_instances_dict[username]
            keyboard_with_link_preview = [[
                InlineKeyboardButton("Watch the live",
                                     url=f'http://chaturbate.com/{username}'),
                InlineKeyboardButton(
                    "Update stream image",
                    callback_data='view_stream_image_callback_' + username)
            ]]
            keyboard_without_link_preview = [[
                InlineKeyboardButton("Watch the live",
                                     url=f'http://chaturbate.com/{username}')
            ]]
            markup_with_link_preview = InlineKeyboardMarkup(
                keyboard_with_link_preview)
            markup_without_link_preview = InlineKeyboardMarkup(
                keyboard_without_link_preview)

            try:

                if model_instance.status != "error":
                    for chatid_tuple in chat_and_online_dict[username]:
                        chat_id = chatid_tuple.chat_id
                        db_status = chatid_tuple.online

                        if model_instance.online and db_status == False:

                            if model_instance.status in {
                                    "away", "private", "hidden", "password"
                            }:  # assuming the user knows the password
                                Utils.alchemy_instance.session.query(
                                    ChaturbateUser).filter(
                                        ChaturbateUser.username == username
                                        and ChaturbateUser.chat_id
                                        == chat_id).update(
                                            {ChaturbateUser.online: True},
                                            synchronize_session=False)
                                send_message(
                                    chat_id,
                                    f"{username} is now <b>online</b>!\n<i>No link preview can be provided</i>",
                                    bot,
                                    html=True,
                                    markup=markup_without_link_preview)
                            else:
                                Utils.alchemy_instance.session.query(
                                    ChaturbateUser).filter(
                                        ChaturbateUser.username == username
                                        and ChaturbateUser.chat_id
                                        == chat_id).update(
                                            {ChaturbateUser.online: True},
                                            synchronize_session=False)

                                if Preferences.get_user_link_preview_preference(
                                        chat_id
                                ) and model_instance.model_image is not None:
                                    send_image(
                                        chat_id,
                                        model_instance.model_image,
                                        bot,
                                        markup=markup_with_link_preview,
                                        caption=
                                        f"{username} is now <b>online</b>!",
                                        html=True)
                                else:
                                    send_message(
                                        chat_id,
                                        f"{username} is now <b>online</b>!",
                                        bot,
                                        html=True,
                                        markup=markup_without_link_preview)

                        elif model_instance.online == False and db_status:
                            Utils.alchemy_instance.session.query(
                                ChaturbateUser).filter(
                                    ChaturbateUser.username == username and
                                    ChaturbateUser.chat_id == chat_id).update(
                                        {ChaturbateUser.online: False},
                                        synchronize_session=False)
                            send_message(chat_id,
                                         f"{username} is now <b>offline</b>",
                                         bot,
                                         html=True)

                        if model_instance.status == "deleted":
                            Utils.alchemy_instance.session.query(
                                ChaturbateUser).filter_by(
                                    username=username, chat_id=chat_id).delete(
                                        synchronize_session=False)
                            send_message(
                                chat_id,
                                f"{username} has been removed because room has been deleted",
                                bot)
                            logging.info(
                                f"{username} has been removed from {chat_id} because room has been deleted"
                            )

                        elif model_instance.status == "banned":
                            Utils.alchemy_instance.session.query(
                                ChaturbateUser).filter_by(
                                    username=username, chat_id=chat_id).delete(
                                        synchronize_session=False)
                            send_message(
                                chat_id,
                                f"{username} has been removed because room has been banned",
                                bot)
                            logging.info(
                                f"{username} has been removed from {chat_id} because has been banned"
                            )

                        elif model_instance.status == "canceled":
                            Utils.alchemy_instance.session.query(
                                ChaturbateUser).filter_by(
                                    username=username, chat_id=chat_id).delete(
                                        synchronize_session=False)
                            send_message(
                                chat_id,
                                f"{username} has been removed because room has been canceled",
                                bot)
                            logging.info(
                                f"{username} has been removed from {chat_id} because has been canceled"
                            )

                        elif model_instance.status == "geoblocked":
                            Utils.alchemy_instance.session.query(
                                ChaturbateUser).filter_by(
                                    username=username, chat_id=chat_id).delete(
                                        synchronize_session=False)
                            send_message(
                                chat_id,
                                f"{username} has been removed because of geoblocking",
                                bot)
                            logging.info(
                                f"{username} has been removed from {chat_id} because of geoblocking"
                            )

            except Exception as e:
                Utils.handle_exception(e)
예제 #5
0
def send_message(chatid: str,
                 messaggio: str,
                 bot_p: updater.bot,
                 html: bool = False,
                 markup=None) -> None:
    """
    Sends a message to a telegram user and sends "typing" action


    :param chatid: The chatid of the user who will receive the message
    :param messaggio: The message who the user will receive
    :param bot_p: telegram bot instance
    :param html: Enable html markdown parsing in the message
    :param markup: The reply_markup to use when sending the message
    """

    disable_webpage_preview = not Preferences.get_user_link_preview_preference(
        chatid)  # the setting is opposite of preference

    notification = not Preferences.get_user_notifications_sound_preference(
        chatid)  # the setting is opposite of preference

    try:
        bot_p.send_chat_action(chat_id=chatid, action="typing")
        if html and markup is not None:
            bot_p.send_message(
                chat_id=chatid,
                text=messaggio,
                parse_mode=telegram.ParseMode.HTML,
                disable_web_page_preview=disable_webpage_preview,
                reply_markup=markup,
                disable_notification=notification)
        elif html:
            bot_p.send_message(
                chat_id=chatid,
                text=messaggio,
                parse_mode=telegram.ParseMode.HTML,
                disable_web_page_preview=disable_webpage_preview,
                disable_notification=notification)
        elif markup is not None:
            bot_p.send_message(
                chat_id=chatid,
                text=messaggio,
                disable_web_page_preview=disable_webpage_preview,
                reply_markup=markup,
                disable_notification=notification)
        else:
            bot_p.send_message(
                chat_id=chatid,
                text=messaggio,
                disable_web_page_preview=disable_webpage_preview,
                disable_notification=notification)
    except Unauthorized:  # user blocked the bot
        if auto_remove:
            logging.info(
                f"{chatid} blocked the bot, he's been removed from the database"
            )
            Utils.alchemy_instance.session.query(ChaturbateUser).filter_by(
                chat_id=str(chatid)).delete(synchronize_session=False)
            Preferences.remove_user_from_preferences(chatid)
    except Exception as e:
        Utils.handle_exception(e)
예제 #6
0
def send_image(chatid: str,
               image,
               bot_p: updater.bot,
               html: bool = False,
               markup=None,
               caption=None) -> None:
    """
    Sends an image to a telegram user and sends "sending image" action


    :param caption: Photo caption
    :param chatid: The chatid of the user who will receive the message
    :param image: The image to send
    :param bot_p: telegram bot instance
    :param html: Enable html markdown parsing in the message
    :param markup: The reply_markup to use when sending the message
    """

    notification = not Preferences.get_user_notifications_sound_preference(
        chatid)  # the setting is opposite of preference

    try:
        bot_p.send_chat_action(chatid, action="upload_photo")
        if html and markup is not None and caption is not None:
            bot_p.send_photo(chat_id=chatid,
                             photo=image,
                             parse_mode=telegram.ParseMode.HTML,
                             reply_markup=markup,
                             disable_notification=notification,
                             caption=caption)
        elif html and markup is not None:
            bot_p.send_photo(chat_id=chatid,
                             photo=image,
                             parse_mode=telegram.ParseMode.HTML,
                             reply_markup=markup,
                             disable_notification=notification)
        elif markup is not None and caption is not None:
            bot_p.send_photo(chat_id=chatid,
                             photo=image,
                             reply_markup=markup,
                             disable_notification=notification,
                             caption=caption)
        elif html and caption is not None:
            bot_p.send_photo(chat_id=chatid,
                             photo=image,
                             parse_mode=telegram.ParseMode.HTML,
                             disable_notification=notification,
                             caption=caption)
        elif html:
            bot_p.send_photo(chat_id=chatid,
                             photo=image,
                             parse_mode=telegram.ParseMode.HTML,
                             disable_notification=notification)
        elif markup is not None:
            bot_p.send_photo(chat_id=chatid,
                             photo=image,
                             reply_markup=markup,
                             disable_notification=notification)
        elif caption is not None:
            bot_p.send_photo(chat_id=chatid,
                             photo=image,
                             disable_notification=notification,
                             caption=caption)
        else:
            bot_p.send_photo(chat_id=chatid,
                             photo=image,
                             disable_notification=notification)
    except Unauthorized:  # user blocked the bot
        if auto_remove:
            logging.info(
                f"{chatid} blocked the bot, he's been removed from the database"
            )
            Utils.alchemy_instance.session.query(ChaturbateUser).filter_by(
                chat_id=str(chatid)).delete(synchronize_session=False)
            Preferences.remove_user_from_preferences(chatid)
    except Exception as e:
        Utils.handle_exception(e)
예제 #7
0
    def update_model_status(self):
        """
        Updates self.online and self.status
        """
        for attempt in range(5):
            # noinspection PyBroadException
            try:
                self.last_update = datetime.datetime.now()
                target = f"https://en.chaturbate.com/api/chatvideocontext/{self.username}"
                headers = {
                    'user-agent':
                    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36',
                }
                self._response = requests.get(target, headers=headers)

            except Exception:
                self._response = None
                logging.info(self.username +
                             " has failed to connect on attempt " +
                             str(attempt))
                time.sleep(3)  # sleep and retry
            else:
                break

        if self._response is None:
            logging.info(self.username +
                         " has failed to connect after all attempts")
            self.status = "error"

        elif b"It's probably just a broken link, or perhaps a cancelled broadcaster." in self._response.content:  # check if models still exists
            self.status = "canceled"

        elif self._response.status_code == 401:
            self._response = json.loads(self._response.content)
            if "Room is deleted" in str(self._response['detail']):
                self.status = "deleted"
            elif "This room has been banned" in str(self._response['detail']):
                self.status = "banned"
            elif "This room is not available to your region or gender." in str(
                    self._response['detail']):
                self.status = "geoblocked"
            elif "This room requires a password" in str(
                    self._response['detail']):
                self.status = "password"
            else:
                self.status = "error"

        elif self._response.status_code == (200 and 401):
            logging.error(
                f'{self.username} got a {self._response.status_code} error')
            self.status = "error"

        else:
            try:
                self._response = json.loads(self._response.content)
            except Exception as e:
                Utils.handle_exception(e)
                logging.critical(
                    "This response should have been json decodable")
                try:
                    logging.critical(str(self._response.content))
                except Exception as e:
                    Utils.handle_exception(e)
                    logging.critical("The response could not be printed")
                self.status = "error"
            else:
                self.status = self._response["room_status"]

        if self.status in {
                "offline", "error", "deleted", "banned", "geoblocked",
                "canceled"
        }:
            self.online = False
        else:
            self.online = True
예제 #8
0
    def update_status() -> None:
        username_list = []
        chat_and_online_dict={}

        # create a dictionary with usernames and online using distinct
        results = Utils.retrieve_query_results("SELECT DISTINCT USERNAME FROM CHATURBATE")
        for row in results:
            username_list.append(row[0])

        # obtain chatid
        for username in username_list:
            results = Utils.retrieve_query_results(f"SELECT DISTINCT CHAT_ID, ONLINE FROM CHATURBATE WHERE USERNAME='******'")
            chat_and_online_dict[username]=results # assign (chatid,online) to every model


        # Threaded function for queue processing.
        def crawl(q, model_instances_dict):
            while not q.empty():
                work = q.get()  # fetch new work from the Queue
                username = Utils.sanitize_username(work[1])
                model_instance=Model(username,autoupdate=False)
                model_instance.update_model_status()
                try:
                    model_instance.update_model_image()
                except Exception:
                    model_instance.model_image = None  # set to None just to be secure Todo: this may be extra

                model_instances_dict[username] = model_instance
                # signal to the queue that task has been processed
                q.task_done()
            return True

        q = Queue(maxsize=0)
        # Populating Queue with tasks
        model_instances_dict = {}

        # load up the queue with the username_list to fetch and the index for each job (as a tuple):
        for index, value in enumerate(username_list):
            # need the index and the username in each queue item.
            q.put((index, value))

            # Starting worker threads on queue processing
        for i in range(http_threads):
            worker = threading.Thread(target=crawl, args=(q, model_instances_dict), daemon=True)
            worker.start()
            time.sleep(wait_time)  # avoid server spamming by time-limiting the start of requests

        # now we wait until the queue has been processed
        q.join()

        for username in username_list:
            model_instance = model_instances_dict[username]
            keyboard_with_link_preview = [[InlineKeyboardButton("Watch the live", url=f'http://chaturbate.com/{username}'),
                                           InlineKeyboardButton("Update stream image",callback_data='view_stream_image_callback_' + username)]]
            keyboard_without_link_preview = [
                [InlineKeyboardButton("Watch the live", url=f'http://chaturbate.com/{username}')]]
            markup_with_link_preview = InlineKeyboardMarkup(keyboard_with_link_preview)
            markup_without_link_preview = InlineKeyboardMarkup(keyboard_without_link_preview)



            try:

                if model_instance.status != "error":
                    for chatid_tuple in chat_and_online_dict[username]:
                        chat_id=chatid_tuple[0]
                        db_status=chatid_tuple[1]

                        if model_instance.online and db_status == "F":

                            if model_instance.status in {"away", "private", "hidden", "password"}:  # assuming the user knows the password
                                Utils.exec_query(f"UPDATE CHATURBATE SET ONLINE='T' WHERE USERNAME='******' AND CHAT_ID='{chat_id}'")
                                send_message(chat_id, f"{username} is now <b>online</b>!\n<i>No link preview can be provided</i>", bot, html=True,
                                                     markup=markup_without_link_preview)
                            else:
                                Utils.exec_query(
                                    f"UPDATE CHATURBATE SET ONLINE='T' WHERE USERNAME='******' AND CHAT_ID='{chat_id}'")

                                if Preferences.get_user_link_preview_preference(chat_id) and model_instance.model_image != None:
                                        send_image(chat_id, model_instance.model_image, bot, markup=markup_with_link_preview,
                                               caption=f"{username} is now <b>online</b>!", html=True)
                                else:
                                        send_message(chat_id,f"{username} is now <b>online</b>!",bot,html=True,markup=markup_without_link_preview)

                        elif model_instance.online==False and db_status == "T":
                                Utils.exec_query(
                                    f"UPDATE CHATURBATE SET ONLINE='F' WHERE USERNAME='******' AND CHAT_ID='{chat_id}'")
                                send_message(chat_id, f"{username} is now <b>offline</b>", bot, html=True)


                        if model_instance.status=="deleted":
                            Utils.exec_query(f"DELETE FROM CHATURBATE WHERE USERNAME='******' AND CHAT_ID='{chat_id}'")
                            send_message(chat_id, f"{username} has been removed because room has been deleted", bot)
                            logging.info(f"{username} has been removed from {chat_id} because room has been deleted")

                        elif model_instance.status=="banned":
                            Utils.exec_query(f"DELETE FROM CHATURBATE WHERE USERNAME='******' AND CHAT_ID='{chat_id}'")
                            send_message(chat_id, f"{username} has been removed because room has been banned", bot)
                            logging.info(f"{username} has been removed from {chat_id} because has been banned")

                        elif model_instance.status=="canceled":
                            Utils.exec_query(f"DELETE FROM CHATURBATE WHERE USERNAME='******' AND CHAT_ID='{chat_id}'")
                            send_message(chat_id, f"{username} has been removed because room has been canceled", bot)
                            logging.info(f"{username} has been removed from {chat_id} because has been canceled")

                        elif model_instance.status=="geoblocked":
                            Utils.exec_query(f"DELETE FROM CHATURBATE WHERE USERNAME='******' AND CHAT_ID='{chat_id}'")
                            send_message(chat_id,
                                         f"{username} has been removed because of geoblocking",
                                         bot)
                            logging.info(f"{username} has been removed from {chat_id} because of geoblocking")

            except Exception as e:
                Utils.handle_exception(e)