def on_event(self, status):
     '''launches on any streaming event and does auto(like)followback if criteria met'''
     update_states()
     source = status._json.get('source')
     userid = int(source.get('id'))
     screenname = source.get('screen_name')
     username = '******'+screenname
     if status.event == 'follow' and userid in already_followed_array and screenname != myname:
         print('\nincoming followback by',username)
     elif screenname != myname:
         print('\nincoming',status.event,'by',username)
     if config.likeback_opt and status.event == 'favorite' and screenname != myname:
         if userid in following_array or userid in already_followed_array:
             print(username,'is already followed, trying to likeback..')
             tweets = []
             try:
                 for status2_count,status2 in enumerate(tweepy.Cursor(api.user_timeline,id=username).items()):
                         if logger.read('like_allowed_state.txt') == '1' and not bool(status2.in_reply_to_screen_name) and status2.id not in liked_tweets_array:
                             try:
                                 status2.retweeted_status
                             except AttributeError:
                                 try:
                                     status2.favorite()
                                     liked_tweets_array.add(status2.id)
                                     print('success')
                                     break
                                 except tweepy.TweepError as e:
                                     if '429' in str(e.reason):
                                         print('\ncode 429 detected! you probably ran out of daily like limit\n\ndisabling likes for now..')
                                         logger.save('0','like_allowed_state.txt')
                                     if '139' in str(e.reason):
                                         liked_tweets_array.add(status2.id)
                                     else:
                                         print(e.reason)
                                         break
                         if status2_count > 18:
                             print('only retweets so no like for them')
                             break
             except tweepy.TweepError as e:
                 print(e.reason)
         elif logger.read('follow_allowed_state.txt') == '1' and not userid in already_followed_array and screenname != myname:
             try:
                 api.create_friendship(userid)
                 print('followed',username)
                 following_array.add(userid)
                 already_followed_array.add(userid)
                 logger.add_followed(userid)
             except tweepy.TweepError as e:
                 print(e.reason)
                 if '161' in str(e.reason):
                     print('\ncode 161 detected! you probably ran out of daily following limit\n\ndisabling followback for now..')
                     logger.save('0','follow_allowed_state.txt')
     if config.instafollowback_opt and status.event == 'follow':
         if not userid in following_array and not userid in already_followed_array and screenname != myname:
             api.create_friendship(userid)
             print('followback',username)
def media(gif, alt, proxify):
    faces_detected = False
    media = ''
    service_name = ''
    part = 0
    pixiv_id = 0
    danbooru_id = 0
    member_name = ''
    title = ''
    ext_urls = []
    est_time = ''
    minsim = 70
    predictions = []
    '''pick random image from folder'''
    if alt:
        media_list = glob(config.source_folder_alt + '*')
    else:
        media_list = glob(config.source_folder + '*')
    if gif:
        while not media.lower().endswith(('gif')):
            media = choice(media_list)
    else:
        while not media.lower().endswith(('.png', '.jpg', '.jpeg', 'gif')):
            media = choice(media_list)
    print('\nopened', media)
    '''check if it was tweeted and size'''
    if media in set(logger.read_posts()):
        print('pic was already tweeted, trying another file..')
        return '', '', '', '', 10, '', False, 0, ''
    if path.getsize(media) < config.discard_size * 1000:
        print(int(path.getsize(media) / 1000), 'KB <', config.discard_size,
              'KB, trying another file..')
        return '', '', '', '', 10, '', False, 0, ''
    media_log = media
    '''run neural network if enabled and installed'''
    neural_opt = config.neural_opt
    if neural_opt:
        try:
            import moeflow
            if not media.lower().endswith(('.gif')):
                predictions, faces_detected = moeflow.neuralnetwork(media)
        except Exception as e:
            print(
                e,
                '\nneural network not avaliable! some functions are limited :<'
            )
            neural_opt = False
    '''compress pic and upload it to saucenao.com'''
    thumbSize = (150, 150)
    image = Image.open(media)
    image.thumbnail(thumbSize, Image.ANTIALIAS)
    imageData = BytesIO()
    image.save(imageData, format='PNG')
    files = {'file': ('image.png', imageData.getvalue())}
    imageData.close()
    print('\nsending pic to saucenao.com')
    try:
        if proxify:
            r = post(
                'http://saucenao.com/search.php?output_type=2&numres=10&minsim='
                + str(minsim) + '!&db=999&api_key=' + config.alt_key_saucenao,
                files=files,
                timeout=60,
                proxies={
                    'http': config.proxy,
                    'https': config.proxy
                })
        else:
            r = post(
                'http://saucenao.com/search.php?output_type=2&numres=10&minsim='
                + str(minsim) + '!&db=999&api_key=' + config.api_key_saucenao,
                files=files,
                timeout=60)
    except Exception as e:
        print(e)
        return media, '', '', '', 'api_na', '', faces_detected, 0, media_log
    if r.status_code != 200:
        if r.status_code == 403:
            exit(
                '\napi key error! enter proper saucenao api key in settings.txt\n\nget it here https://saucenao.com/user.php?page=search-api'
            )
        elif r.status_code == 429:
            if config.proxy != 'socks5://user:password@hostname:port' and config.alt_key_saucenao != '':
                print('\nswitching to another saucenao api key..')
            else:
                print(
                    '\nsaucenao.com api rate limit exceeded! pls fill api_key_saucenao_alt and proxy in settings or wait'
                )
            return '', '', '', '', 11, '', False, 0, ''
        else:
            print('saucenao.com api unknown error! status code: ' +
                  str(r.status_code))
    else:
        logger.save(r.text, 'last_saucenao_response.txt')  #debug
        results = JSONDecoder(object_pairs_hook=OrderedDict).decode(
            r.text)  #convert json response to dict
        print('remaining searches 30s|24h: ' +
              str(results['header']['short_remaining']) + '|' +
              str(results['header']['long_remaining']))
    '''check pic metainfo in saucenao.com response'''
    if float(results['results'][0]['header']['similarity']) > minsim:
        print('hit! ' + str(results['results'][0]['header']['similarity'] +
                            ' analyzing response..'))
        index_id = results['results'][0]['header']['index_id']
        if index_id == 21:
            part = results['results'][0]['data']['part']
            est_time = results['results'][0]['data']['est_time']
            source = results['results'][0]['data']['source']
            ext_urls = results['results'][0]['data']['ext_urls']
        else:
            result = 0
            while danbooru_id == 0 and result < 10:
                try:
                    if float(results['results'][result]['header']
                             ['similarity']) > minsim:
                        danbooru_id = results['results'][result]['data'][
                            'danbooru_id']
                except Exception:
                    pass
                result += 1
            if index_id == 5 or index_id == 6:
                pixiv_id = results['results'][0]['data']['pixiv_id']
                member_name = results['results'][0]['data']['member_name']
                title = results['results'][0]['data']['title']
            result = 0
            while result < 10:
                try:
                    if float(results['results'][result]['header']
                             ['similarity']) > minsim:
                        ext_urls = results['results'][result]['data'][
                            'ext_urls']
                except Exception:
                    pass
                result += 1
        if ext_urls != []:
            for url in ext_urls:
                if not 'pixiv' in url:
                    cleanup()
                    try:
                        call(
                            ['image-scraper', url],
                            timeout=60)  #trying to download better quality pic
                    except Exception as e:
                        print(e)
                    if find_biggest() == '':
                        pass
                    elif biggest[1] >= 5242880:
                        unlink(biggest[0])
                        find_biggest()
                        if biggest[1] >= path.getsize(media):
                            media = biggest[0]
                            break
                    elif biggest[1] >= path.getsize(media):
                        print('found better quality pic:',
                              int(biggest[1] / 1000), 'KB >',
                              int(path.getsize(media) / 1000), 'KB')
                        media = biggest[0]
                        break
    else:
        print('miss... ' + str(results['results'][0]['header']['similarity']),
              '\n\ntrying another pic..')
        return media, '', '', '', 0, '', False, 0, media_log
    if path.getsize(media) <= 250000:
        print('low quality, trying another pic..')
        return media, '', '', '', 0, '', False, 0, media_log
    if pixiv_id != 0:
        return media, str(title), str(
            member_name
        ), 'https://www.pixiv.net/member_illust.php?mode=medium&illust_id=' + str(
            pixiv_id), 1, predictions, faces_detected, danbooru_id, media_log
    elif part != 0:
        return media, str(source) + ' ep. ' + str(
            part) + ' | timecode: ' + str(est_time), '', ext_urls[
                0], 2, predictions, faces_detected, danbooru_id, media_log
    else:
        return media, '', '', ext_urls[
            0], 1, predictions, faces_detected, danbooru_id, media_log
def steal_followers(following_array, followers_array, myid, following_counter, following_now_counter):
    '''follows people who follow your target'''
    if input('\nWARNING!!1! stealing followers may lead to PERMANENT BAN (tested 06/2k18) use normal following routine instead\n\nbut if youre feeling lucky press y to continue:') != 'y':
        exit()
    update_states()
    if logger.read('follow_allowed_state.txt') == '0':
        print('\nfollowing temporarily not allowed! sleeping 5 min..')
        time.sleep(300)
        return 'restart', following_now_counter
    following_array = set(following_array)
    already_checked_array = logger.read_checked()
    already_followed_array = logger.read_followed()
    target_followers_array = []
    for page in tweepy.Cursor(api.followers_ids, id=input('\nenter username whom followers you wanna steal (without @): ')).pages():
        target_followers_array.extend(page)
        if len(target_followers_array) > 18000:
            break
    for userid in target_followers_array:
        if following_counter >= config.custom_following_limit:
            return 'custom_following_limit_hit', following_now_counter
        elif following_counter >= len(followers_array) + randint(4888,5000):
            sleep_time = randint(18000,36000)
            print('\nfollowing cycle stopped, following hardlimit hit:',len(followers_array),'\nsleeping',sleep_time,'sec..\n')
            time.sleep(sleep_time)
            return 'following_hardlimit_hit',following_now_counter
        elif following_counter >= 4999 and len(followers_array) < 4999:
            sleep_time = randint(18000,36000)
            print('\nfollowing cycle stopped, following hardlimit hit: 5000\nsleeping',sleep_time,'sec..\n')
            time.sleep(sleep_time)
            return 'following_hardlimit_hit',following_now_counter
        followed_state = False
        if userid in already_checked_array:
            print('already checked userid:',userid,'\n')
        elif userid in already_followed_array:
            print('already tried to follow userid:',userid,'\n')
            followed_state = True
        elif userid in following_array:
            print('already following userid:',userid,'\n')
        elif not config.followback_opt and userid in followers_array:
            print('userid already follows us:',userid,'\n')
        else:
            try:
                user = api.get_user(userid)
                userid_followers_count = user.followers_count
                userid_following_count = user.friends_count
                if userid_following_count < userid_followers_count - userid_followers_count*0.1:
                        print(user.screen_name,'doesnt seems like mutual\n')
                elif userid_followers_count < config.min_followers:
                    print(user.screen_name,'doesnt have enough followers\n')
                elif userid_following_count > 200 and userid_following_count > 3*userid_followers_count:
                    print(user.screen_name,'follows more than 3x his followers\n')
                elif user.default_profile_image or user.default_profile:
                    print(user.screen_name,'not customized profile\n')
                elif user.protected:
                    print(user.screen_name,'locked his account\n')
                else:
                    try:
                        for status2 in tweepy.Cursor(api.user_timeline,id=userid).items():
                            if time.mktime(datetime.datetime.strptime(str(status2.created_at), '%Y-%m-%d %H:%M:%S').timetuple()) < time.time() - 24*60*60:
                                print(user.screen_name,'is inactive\n')
                            else:
                                try:
                                    user.follow()
                                    following_counter += 1
                                    following_now_counter += 1
                                    if not userid in already_followed_array:
                                        already_followed_array.add(userid)
                                        logger.add_followed(userid)
                                    followed_state = True
                                    sleep_time = uniform(50,100)
                                    print('followed',user.screen_name,'| total following:',following_counter,'| followed now:',following_now_counter,'\nsleeping',sleep_time,'sec to avoid detection..\n')
                                    time.sleep(sleep_time)
                                except tweepy.TweepError as e:
                                    print(e.reason)
                                    if '161' in str(e.reason):
                                        logger.save('0','follow_allowed_state.txt')
                                        sleep_time = randint(18000,36000)
                                        print('\ncode 161 detected! you probably ran out of daily following limit\n\nsleeping',sleep_time,'sec before next try..')
                                        time.sleep(sleep_time)
                            break
                    except tweepy.TweepError as e:
                        print(e.reason)
            except tweepy.TweepError as e:
                if '63' in str(e.reason):
                    print('user was banned')
        if not followed_state:
            already_checked_array.add(userid)
            logger.add_checked(userid)
    print('successfully checked',len(target_followers_array),'users and followed',following_now_counter,'of them')
    return 'restart', following_now_counter
def update_states():
    '''check follow/like cooldown'''
    if time.time() - logger.fmtime('like_allowed_state.txt') > 3600:
        logger.save('1','like_allowed_state.txt')
    if time.time() - logger.fmtime('follow_allowed_state.txt') > 14400:
        logger.save('1','follow_allowed_state.txt')
def search_new_followers(followers_array, following_counter, search_phrase, following_now_counter):
    '''finds tweets and follows author if all checks passed (and likes tweet if set)'''
    update_states()
    if logger.read('follow_allowed_state.txt') == '0':
        print('\nfollowing temporarily not allowed! sleeping 5 min..')
        time.sleep(300)
        return 'restart', following_now_counter
    already_checked_array = logger.read_checked()
    already_followed_array = logger.read_followed()
    for status in tweepy.Cursor(api.search, q=search_phrase).items():
        if following_counter >= config.custom_following_limit:
                return 'custom_following_limit_hit', following_now_counter
        elif following_counter >= len(followers_array) + randint(4888,5000):
            sleep_time = randint(18000,36000)
            print('\nfollowing cycle stopped, following hardlimit hit:',len(followers_array),'\nsleeping',sleep_time,'sec..\n')
            time.sleep(sleep_time)
            return 'following_hardlimit_hit',following_now_counter
        elif following_counter >= 4999 and len(followers_array) < 4999:
            sleep_time = randint(18000,36000)
            print('\nfollowing cycle stopped, following hardlimit hit: 5000\nsleeping',sleep_time,'sec..\n')
            time.sleep(sleep_time)
            return 'following_hardlimit_hit',following_now_counter
        try:
            userid = status.user.id
            username = '******'+status.user.screen_name
            if userid in followers_array and not config.followback_opt:
                print('\n',username,'already follows us..')
            elif userid in already_followed_array:
                print('\nalready tried to follow',username,'in the past..')
            elif status.user.following:
                print('\nalready following',username,'(not by script)..')
            else:
                userid_followers_count = status.user.followers_count
                userid_following_count = status.user.friends_count
                if userid_following_count < userid_followers_count - userid_followers_count*0.1:
                    print('\n',username,'doesnt seems like mutual')
                elif userid_followers_count < config.min_followers:
                    print('\n',username,'doesnt have enough followers')
                elif userid_following_count > 200 and userid_following_count > 2*userid_followers_count:
                    print('\n',username,'follows more than 2x his followers')
                elif status.user.default_profile_image or status.user.default_profile:
                    print('\n',username,'not customized profile')
                else:
                    if config.anime_avi_opt:
                        profile_pic = logger.save_profile_pic(status.user.profile_image_url_https.replace('_normal',''))
                    if not config.anime_avi_opt or face_detect.run_face_detection(profile_pic): #detect anime avi
                        status.user.follow()
                        following_now_counter += 1
                        following_counter += 1
                        if not userid in already_followed_array:
                            already_followed_array.add(userid)
                            logger.add_followed(userid)
                        sleep_time = uniform(50,100)
                        print('\nfollowed',username,'| total following:',following_counter,'| followed now:',following_now_counter,'\nsleeping',sleep_time,'sec to avoid detection..')
                        time.sleep(sleep_time)
                    else:
                        print('\n',username,'avi doesnt seems like anime')
                    try:
                        remove(profile_pic)
                    except Exception:
                        pass
                    if config.like_opt and logger.read('like_allowed_state.txt') == '1':
                        status.favorite()
                        print('liked this tweet')
                    time.sleep(sleep_time)
        except tweepy.TweepError as e:
            print(e.reason)
            if '161' in str(e.reason):
                sleep_time = randint(18000,36000)
                print('\ncode 161 detected! you probably ran out of daily following limit\n\nsleeping',sleep_time,'sec before next try..')
                logger.save('0','follow_allowed_state.txt')
                time.sleep(sleep_time)
                return 'restart', following_now_counter
        except StopIteration:
            print('\nwe searched all tweets, sleeping 5 minutes before next try..')
            time.sleep(300)
            return 'restart', following_now_counter
        already_checked_array.add(userid)
    print('following cycle crashed for some reason, restarting in',sleep_time,'sec')
    time.sleep(sleep_time)
    return 'restart', following_now_counter