Beispiel #1
0
 def execute(self, delay):
   user = self.tweet.user
   res = self.make_request(constants.FOLLOW_URL, error_delay=delay)
   if res.status_code != 200:
     logger.error(f'failed to follow {user.username}')
   else:
     logger.info(f'followed: {user.username}')
Beispiel #2
0
  def execute(self, delay):
    time.sleep(delay)

    res = self.make_request(url=constants.LIKE_URL, error_delay=delay)

    if res.status_code != 200:
      logger.error(f'failed to like: {self.tweet}')
    else:
      logger.info(f'liked: {self.tweet}')
Beispiel #3
0
 def execute(self):
   while True:
     actions = self._queue.get()
     if actions is _sentinel:
       self._queue.put(_sentinel)
       self._queue.task_done()
       break
     if not isinstance(actions, collections.Iterable):
       actions = (actions, )
     for action in actions:
       if not isinstance(action, Action):
         logger.error(f'expected object of Action type, got {type(action)}')
         continue
       action.execute(self._delay)
     self._queue.task_done()
Beispiel #4
0
 def make_request(self, url, method='post',
                 error_delay=5, tries=10, allow_redirects=False):
   with self.get_session() as session:
     while tries > 0:
       try:
         request = getattr(session, method.lower())
         res = request(
           url = url,
           data = self.payload,
           allow_redirects = allow_redirects
         )
         return res
       except Exception as ex:
         logger.error(ex) # TODO: remove this
         time.sleep(error_delay)
         tries -= 1
Beispiel #5
0
  def get_session(self):
    username = os.environ['username']
    session = create_session(username)
    cookies = requests.utils.dict_from_cookiejar(session.cookies)

    if 'ct0' not in cookies:
      logger.error(f'{username}\'s session has expired. Log in again')
      clear(silent=True)
      os._exit(1) # TODO: a better way to do this?

    session.headers['User-Agent'] = ua_provider.fetch()
    session.headers['Authorization'] = constants.BEARER
    session.headers['X-Twitter-Auth-Type'] = 'OAuth2Session'
    session.headers['X-Twitter-Active-User'] = '******'
    session.headers['Origin'] = constants.BASE_URL
    session.headers['x-csrf-token'] = cookies['ct0']

    return session
Beispiel #6
0
  def _make_request(self, query, limit=None):
    params = {
      'vertical': 'default',
      'src': 'typd',
      'include_available_features': '1',
      'include_entities': '1',
      'q': query
    }

    if bool(random.getrandbits(1)):
      params['f'] = 'tweets' # this will fetch the latest

    if limit is not None:
      params['max_position'] = limit

    tries = self._error_tries
    with create_session(os.environ['username']) as session:
      # set headers
      session.headers['Accept'] = 'application/json, text/javascript, */*; q=0.01'
      session.headers['Accept-Language'] = 'en-US,en;q=0.5'
      session.headers['Referer'] = constants.SEARCH_URL
      session.headers['X-Requested-With'] = 'XMLHttpRequest'
      session.headers['X-Twitter-Active-User'] = '******'
      while tries > 0:
        try:
          session.headers['User-Agent'] = ua_provider.fetch()
          res = session.get(constants.TIMELINE_SEARCH_URL, params=params)
          data = res.json()
          # check if we have what we need
          data['inner']['items_html']
          return data['inner']
        except Exception as e:
          logger.error(f'{self._error_tries - tries }-search request has failed:\n{e}')
          time.sleep(self._error_delay)
          tries -= 1
    logger.error(f'failed to make the search request: {query}')
    exit()
Beispiel #7
0
def login(username, password, tries=10, delay=2):
  with create_session(username) as session:
    res = session.get(constants.LOGIN_URL)
    soup = BeautifulSoup(res.text,"html.parser")
    token = soup.select_one("[name='authenticity_token']")['value']

    payload = {
      'session[username_or_email]':username,
      'session[password]': password,
      'authenticity_token':token,
      'ui_metrics': constants.UI_METRICS,
      'authenticity_token':token,
      'remember_me':1
    }

    session.headers['Origin'] = constants.BASE_URL
    session.headers['Referer'] = constants.LOGIN_URL
    session.headers['Upgrade-Insecure-Requests'] = '1'

    time.sleep(5) # pause a bit

    while tries > 0:
      try:
        session.headers['User-Agent'] = ua_provider.fetch()
        res = session.post(constants.SESSIONS_URL, data=payload, allow_redirects=False)
        res.raise_for_status()
        if 'location' in res.headers:
          url = res.headers['location']
          if 'locked' in url:
            logger.error('Too many attempts. Your account has been locked (60 mins).')
            exit()
          elif 'error' in url:
            raise InvalidCredentials
        if 'auth_token' in res.cookies.get_dict():
          typing.cast(FileCookieJar, session.cookies).save()
          logger.info(f'You have signed in as {username}')
          return
      except Exception as ex:
        if isinstance(ex, InvalidCredentials):
          raise
        logger.error(f'Error while signing in:\n{ex}')
        pass
      time.sleep(delay)
      tries -= 1
    # Twitter won't provide auth_token in cookies or ban
    logger.error(
    '''Failed to sign in. Your IP address (or account) may have been banned (yikes).
       Try logging in through your browser. If you can't log in, then you've been banned.'''
     )
    exit()
Beispiel #8
0
def main():  
  if sys.version_info[0] < 3:
    logger.error('Python 3 or a more recent version is required.')
    exit()

  parser = argparse.ArgumentParser()
  parser.add_argument(
    '-a', '--agents',
    help='File containing user-agents',
    dest='agents_file',
    default=f'{default_config_path}/user-agents.txt'
  )
  parser.add_argument(
    '-i', '--invalidate',
    help='Invalidate all saved sessions',
    dest='invalidate',
    action='store_true'
  )
  parser.add_argument(
    '-v', '--version',
    help='Version of the bot',
    dest='version',
    action='store_true'
  )
  parser.add_argument(
    '-c', '--config',
    help='Configuration file',
    dest='config',
    default=f'{default_config_path}/config.json'
  )
  parser.add_argument(
    '-e', '--executor-count',
    help='How many executors should we have running',
    dest='executor_count',
    default=2
  )

  args = parser.parse_args()

  if args.version:
    logger.info(f'tweebot version: {__version__}')
    exit()

  if args.invalidate:
    _base.clear()

  if args.agents_file:
    ua_provider.load(args.agents_file)

  if not args.config:
    logger.error('You need to provide the path to the config.json file')
    exit()

  config = {}

  try:
    with open(args.config, encoding='UTF-8') as fp:
      config = json.loads(fp.read())
      config['searchers']; config['handlers'] # quick check
  except Exception as ex:
    exit(f'Failed to read config.json .\n {ex}')

  if not 'executors' in config:
    if not args.executor_count:
      logger.error(
        '''You will need to provide configurations
        for the executor object. Check the docs for more info.'''
      )
      exit()
    config['executors'] = [{
      'count': args.executor_count,
      'request-delay': 2
    }]

  while True:
    username = input('Twitter username: '******'Twitter password: '******'Invalid credentials.Try again')
        continue
    os.environ['username'] = username
    break

  tweet_queue = queue.Queue()
  action_queue = queue.Queue()

  for params in config['searchers']:
    searcher = _get_searchers(tweet_queue, params)
    _spin_searchers(searcher['query'], searcher['searchers'])

  for params in config['handlers']:
    handler = _get_handlers(tweet_queue, action_queue, params)
    _spin_handlers(handler)

  for params in config['executors']:
    executors = _get_executors(action_queue, **params)
    _spin_executors(executors)

  tweet_queue.join(); action_queue.join()