示例#1
0
    def save_creds(self):
        """
        Store working instagram credentials (username and password)
        """
        creds = secrets.get_var('instacreds:{}'.format(self.user_id))
        if os.environ.get('PORT') in (None, ""):
            # Localhost
            if not creds:
                creds = dict()
            creds[self.username] = self.password
            secrets.set_var('instacreds:{}'.format(self.user_id), creds)
        else:
            connector = redis.from_url(os.environ.get('REDIS_URL'))
            creds: dict = connector.hgetall('instacreds:{}'.format(
                self.user_id))
            if not creds:
                creds = dict()

            try:
                connector.delete('instacreds:{}'.format(self.user_id))
            except:
                pass

            creds[self.username] = self.password
            connector.hmset('instacreds:{}'.format(self.user_id), creds)
            connector.close()
示例#2
0
    def get_all_creds(self):
        if os.environ.get('PORT') in (None, ""):
            creds = secrets.get_var('instacreds:{}'.format(self.user_id))
            if not creds:
                return None

            hascreds = False
            for cred in creds:
                if creds.get(cred):
                    hascreds = True
                    break
            if not hascreds: return None
            return creds
        else:
            connector = redis.from_url(os.environ.get('REDIS_URL'))
            creds: dict = connector.hgetall('instacreds:{}'.format(
                self.user_id))
            decoded = {}
            for key in creds:
                decoded[key.decode('utf-8')] = creds.get(key).decode('utf-8')

            hascreds = False
            for cred in decoded:
                if decoded.get(cred):
                    hascreds = True
                    break
            if not hascreds: return None
            return decoded
示例#3
0
def error(update, context):
    """Log the error and send a telegram message to notify the developer."""
    # Log the error before we do anything else, so we can see it even if something breaks.
    logger.error(msg="Exception while handling an update:",
                 exc_info=context.error)

    # traceback.format_exception returns the usual python message about an exception, but as a
    # list of strings rather than a single string, so we have to join them together.
    tb_list = traceback.format_exception(None, context.error,
                                         context.error.__traceback__)
    tb = ''.join(tb_list)

    # Build the message with some markup and additional information about what happened.
    # You might need to add some logic to deal with messages longer than the 4096 character limit.
    message = ('<b>An exception was raised while handling an update</b>\n'
               '<pre>{}</pre>').format(html.escape(tb))

    # Finally, send the message
    string = str(secrets.get_var('DEVS')).replace('[', '')
    string = string.replace(']', '')
    string = string.replace(' ', '')
    devs = list(string.split(','))
    for dev in devs:
        context.bot.send_message(chat_id=dev,
                                 text=message,
                                 parse_mode=ParseMode.HTML)
示例#4
0
    def delete_creds(self):
        session = self.get_session()
        self.username = None
        self.password = None

        if os.environ.get('PORT') in (None, ""):
            creds = secrets.get_var(f'instacreds:{self.user_id}')
            try:
                del creds[session]
            except:
                pass
            secrets.set_var('instacreds:{}'.format(self.user_id), creds)

            newsession = None
            for key in list(creds.keys()):
                if key != session:

                    newsession = key
                    self.set_session(key)
                    self.set_username(key)
                    break
            applogger.debug(f'Set session: {newsession}')

            if not newsession:
                self.set_session(None)
        else:
            connector = redis.from_url(os.environ.get('REDIS_URL'))
            creds: dict = connector.hgetall('instacreds:{}'.format(
                self.user_id))
            try:
                del creds[bytes(session, encoding='utf8')]
            except:
                pass

            try:
                connector.delete('instacreds:{}'.format(self.user_id))
            except:
                pass

            connector.hmset('instacreds:{}'.format(self.user_id), creds)
            connector.close()

            newsession = None
            for key in list(creds.keys()):
                key = key.decode('utf-8')
                if key != session:
                    newsession = key
                    self.set_session(key)
                    self.set_username(key)
                    break

            if not newsession:
                self.set_session(None)
示例#5
0
    def get_session(self):
        if os.environ.get('PORT') in (None, ""):
            # Localhost
            session: str = secrets.get_var(f'instasession:{self.user_id}')
        else:
            connector = redis.from_url(os.environ.get('REDIS_URL'))
            session: str = connector.get(f'instasession:{self.user_id}')
            if session:
                session = session.decode('utf-8')
            connector.close()

        if not session:
            return None
        self.username = str(session)
        return str(session)
示例#6
0
def set_message(user_id, message_id):
    if os.environ.get('PORT') not in (None, ""):
        spreadsheet = auth()
        sheet:Worksheet = spreadsheet.get_worksheet(3)
        row = find_by_username(user_id, sheet)
        if row:
            sheet.delete_row(row)
        sheet.append_row([user_id, message_id])
    else:
        messages = secrets.get_var('MESSAGES')
        if not messages:
            secrets.set_var('MESSAGES', {str(user_id): message_id})
        else:
            messages[str(user_id)] = message_id
            secrets.set_var('MESSAGES', messages)
示例#7
0
def auth():
    creds_string = secrets.get_var('GSPREAD_CREDS')
    if creds_string == None:
        # use creds to create a client to interact with the Google Drive API
        scope = [
            'https://spreadsheets.google.com/feeds',
            'https://www.googleapis.com/auth/drive',
            'https://www.googleapis.com/auth/drive.file',
            'https://www.googleapis.com/auth/drive']
        # CREDENTIALS HAVE NOT BEEN INITIALIZED BEFORE
        client_secret = os.environ.get('GCLIENT_SECRET')
        if os.environ.get('PORT') in (None, ""):
            # CODE RUNNING LOCALLY
            applogger.debug('DATABASE: Resorted to local JSON file')
            with open('ffinstabot/config/client_secret.json') as json_file:
                client_secret_dict = json.load(json_file)
        else:
            # CODE RUNNING ON SERVER
            client_secret_dict = json.loads(client_secret)

        creds = ServiceAccountCredentials.from_json_keyfile_dict(
            client_secret_dict, scope)
        creds_string = jsonpickle.encode(creds)
        if os.environ.get('PORT') in (None, ""):
            secrets.set_var('GSPREAD_CREDS', creds_string)
    creds = jsonpickle.decode(creds_string)
    client = gspread.authorize(creds)

    # IF NO SPREADSHEET ENV VARIABLE HAS BEEN SET, SET UP NEW SPREADSHEET
    if secrets.get_var('SPREADSHEET') == None:
        spreadsheet = set_sheet(client)
        return spreadsheet
    else:
        SPREADSHEET = secrets.get_var('SPREADSHEET')
        spreadsheet = client.open_by_key(SPREADSHEET)
        return spreadsheet
示例#8
0
def get_message(user_id):
    if os.environ.get('PORT') not in (None, ""):
        spreadsheet = auth()
        sheet:Worksheet = spreadsheet.get_worksheet(3)
        row_id = find_by_username(user_id, sheet)
        if not row_id:
            return None
        row = get_rows(sheet)[row_id-1]
        message = int(row[1])
        return message
    else:
        messages = secrets.get_var('MESSAGES')
        if not messages:
            return None
        else:
            return messages.get(str(user_id))
示例#9
0
 def report_error(self,
                  error=None,
                  send_screenshot=False,
                  screenshot_name=''):
     string = str(secrets.get_var('DEVS')).replace('[', '')
     string = string.replace(']', '')
     string = string.replace(' ', '')
     devs = list(string.split(','))
     for dev in devs:
         if send_screenshot:
             self.send_photo(
                 chat_id=int(dev),
                 photo=open('{}.png'.format(screenshot_name), 'rb'),
                 caption='There was an error with the FFInstaBot: \n{}'.
                 format(error))
         else:
             self.send_message(
                 chat_id=int(dev),
                 text='There was an error with the FFInstaBot: \n{}'.format(
                     error))
示例#10
0
def get_notification(user_id:int) -> Optional['Notification']: # TODO Change if you implement the scheduler
    """
    Retrive last notification from GSheet Database

    Args:
        user_id (int): Telegram user ID to match

    Returns:
        Notification or None: Notification object (or None if no record is found)
    """
    spreadsheet:Spreadsheet = auth()
    sheet:Worksheet = spreadsheet.get_worksheet(2)
    notis = get_all_notifications(user_id, sheet)
    if not notis:
        return None

    for noti in notis.keys():
        if noti == secrets.get_var(f'instasession:{user_id}'):
            return notis.get(noti)
    return None
示例#11
0
def set_notification(user_id:int, notification:'Notification'):
    """
    Insert Notification inside the GSheet Database

    Args:
        user_id (int): Telegram user ID
        notification (Notification): Notification to insert
    """
    spreadsheet:Spreadsheet = auth()
    sheet:Worksheet = spreadsheet.get_worksheet(2)
    row = find_by_username(str(user_id), sheet)
    notifications = dict()
    if row is not None:
        notifications = get_all_notifications(user_id, sheet)
        sheet.delete_row(row)

    # Add New Notification
    notifications[secrets.get_var(f'instasession:{user_id}')] = notification.to_dict()

    sheet.append_row([str(user_id), notifications])
    log(datetime.utcnow(), user_id, 'SET NOTIFICATION')
示例#12
0
def set_sheet(client:Client):
    """
    Setup spreadsheet database if none exists yet.
    Will save the spreadsheet ID to Heroku Env Variables or to secrets.json file
    The service email you created throught the Google API will create the new spreadsheet and share it with the email you indicated in the GDRIVE_EMAIL enviroment variable. You will find the spreadsheet database in your google drive shared folder.
    Don't change the order of the worksheets or it will break the code.

    :param client: GSpread client to utilize
    :type client: Client
    :return: The newly created spreadsheet
    :rtype: Spreadsheet
    """
    # CREATE SPREADSHEET
    spreadsheet:Spreadsheet = client.create('FFInstaBot')
    secrets.set_var('SPREADSHEET', spreadsheet.id)

    settings = spreadsheet.add_worksheet(title='Settings', rows=6, cols=2)
    settings.append_row(['USER ID', 'SETTINGS'])

    follows = spreadsheet.add_worksheet(title='Follows', rows=50, cols=1)
    follows.append_row(['FOLLOWS'])

    notifications = spreadsheet.add_worksheet(title='Notifications', rows=50, cols=2)
    notifications.append_row(['USER ID', 'LAST NOTIFICATION'])

    messages = spreadsheet.add_worksheet(title='Messages', rows=10, cols=2)
    messages.append_row(['USER ID', 'MESSAGE ID'])

    # CREATE LOGS SHEET
    logs = spreadsheet.add_worksheet(title="Logs", rows="500", cols="3")
    logs.append_row(["TIMESTAMP", "USER ID", "ACTION"])

    # DELETE PRE-EXISTING SHEET
    sheet = spreadsheet.get_worksheet(0)
    spreadsheet.del_worksheet(sheet)

    # SHARE SPREADSHEET
    spreadsheet.share(value=secrets.get_var('GDRIVE_EMAIL'),
                      perm_type="user", role="owner")
    return spreadsheet
示例#13
0
    def get_creds(self):
        session = self.get_session()

        if os.environ.get('PORT') in (None, ""):
            creds = secrets.get_var('instacreds:{}'.format(self.user_id))
            if not creds:
                return False
            else:
                self.set_username(session if isinstance(session, str) else
                                  list(creds.keys())[0])

                if creds.get(self.username):
                    self.set_password(creds.get(self.username))
                    return True
                else:
                    return False
        else:
            connector = redis.from_url(os.environ.get('REDIS_URL'))
            creds: dict = connector.hgetall('instacreds:{}'.format(
                self.user_id))
            connector.close()
            if not creds or list(creds.keys()) == []:
                # No credentials
                return False
            else:
                self.set_username(session if isinstance(session, str) else
                                  list(creds.keys())[0].decode('utf-8'))
                applogger.debug(self.username)
                if creds.get(bytes(self.username, encoding='utf8')):
                    self.set_password(
                        creds.get(bytes(self.username,
                                        encoding='utf8')).decode('utf-8'))
                    print(
                        f'{self.username} {type(self.username)} : {self.password} {type(self.password)}'
                    )
                    return True
                else:
                    return False
示例#14
0
import os, redis
from ffinstabot.config import secrets
from rq import Worker, Queue, Connection

listen = ['high', 'default', 'low']
redis_url = secrets.get_var('REDISTOGO_URL', default='redis://localhost:6379')
conn = redis.from_url(redis_url)

if __name__ == '__main__':
    with Connection(conn):
        worker = Worker(map(Queue, listen))
        worker.work()
示例#15
0
    driver.save_screenshot('error.png')
    bot.report_error('instaclient.__find_element() error.', send_screenshot=True, screenshot_name='error')
    os.remove('error.png')


LOCALHOST = True
queue = None
if os.environ.get('PORT') not in (None, ""):
    # Code running locally
    LOCALHOST = False
    queue = Queue(connection=conn)
    

# Initialize Bot
from ffinstabot.config import secrets
BOT_TOKEN = secrets.get_var('BOT_TOKEN')
URL = secrets.get_var('SERVER_APP_DOMAIN')
PORT = int(os.environ.get('PORT', 5000))
from ffinstabot.bot import telebot

# set connection pool size for bot 
request = Request(con_pool_size=8)
defaults = Defaults(parse_mode=ParseMode.HTML, run_async=True)
q = mq.MessageQueue(all_burst_limit=3, all_time_limit_ms=3000)
telegram_bot = MQBot(BOT_TOKEN, request=request, mqueue=q, defaults=defaults)
updater = Updater(bot=telegram_bot, use_context=True)
applogger.debug(f'Started bot of id: {telegram_bot.id}')

# SET UP BOT COMMAND HANDLERS
telebot.setup(updater)