示例#1
0
    def setUp(self):
        """Constructor for the unittest

        :return:
        """
        self.test_jpg = generate_small_jpg()

        self.saucenao_html = SauceNao(os.getcwd(),
                                      output_type=SauceNao.API_HTML_TYPE,
                                      log_level=logging.DEBUG)
        self.saucenao_json = SauceNao(os.getcwd(),
                                      output_type=SauceNao.API_JSON_TYPE,
                                      log_level=logging.DEBUG)

        self.NOT_IP_LIMIT_NOT_ACCOUNT_LIMIT = [{
            'function': self.check_response_no_api_key,
            'expected_success': True
        }, {
            'function': self.check_response_api_key,
            'expected_success': True
        }]
        self.IP_LIMIT_NOT_ACCOUNT_LIMIT = [{
            'function': self.check_response_no_api_key,
            'expected_success': False
        }, {
            'function': self.check_response_api_key,
            'expected_success': True
        }]
        self.IP_LIMIT_ACCOUNT_LIMIT = [{
            'function': self.check_response_no_api_key,
            'expected_success': False
        }, {
            'function': self.check_response_api_key,
            'expected_success': False
        }]
示例#2
0
def test_check_image_html():
    test_dir = os.path.dirname(__file__)
    with open(os.path.join(test_dir, 'test_data',
                           'test_check_image_html.json')) as f:
        exp_res = json.load(f)
    pic_path = os.path.join(test_dir, 'test_data', 'test_check_image_html.jpg')
    img = Image.new('RGB', (150, 150), color='red')
    img.save(pic_path)
    sn = SauceNao('')
    res = sn.check_image(pic_path, SauceNao.API_HTML_TYPE)
    assert json.loads(res) == exp_res
示例#3
0
def detect_characters(img_path):
    '''Reads the input image to do the following -
        * Detect an anime character from the trained database of characters.
        * Pass the image to cloud library to get visually similar images based on the content of the image.
        * Scrape more images based on the character detected.
    '''

    img = cv2.imread(img_path)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    flag = 0
    for file in os.listdir('cascades'):
        cascade = cv2.CascadeClassifier('cascades/' + str(file))
        detect = cascade.detectMultiScale(gray, 1.3, 5, 0, (100, 100))

        for (x, y, w, h) in detect:
            print('Series: ' + DB[str(file)])
            cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 2)
            flag = 1

            api_data = json.load(open('api_key.json'))
            sauce = SauceNao("", databases=999, minimum_similarity=30, combine_api_types=False,
                             api_key=api_data['saucenao_key'],
                             exclude_categories='', move_to_categories=False, output_type=SauceNao.API_HTML_TYPE, start_file='',
                             log_level=logging.ERROR, title_minimum_similarity=30)

            data = {
                "Records": [{"keywords": CHARACTER_DB[str(file)], "limit": 20, "print_urls": False}]
            }

            print("Uploading image...")

            results = sauce.check_file(img_path)
            print("Evaluating image...\n")
            print(results)
            print("\n")
            print("Getting similar images...")

            with open('config.json', 'w') as outfile:
                json.dump(data, outfile)

            os.system("googleimagesdownload -cf config.json > /dev/null")

            print("Found 20 images similar in content to given image. Check the downloads folder for the downloaded images.")

        if flag == 1:
            break

    cv2.imshow('Image', img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
示例#4
0
    def check_response_api_key(self, saucenao: SauceNao, assert_success=True):
        """Check the response with an API key
        on assert_success=True expect a dictionary, else an exception

        :type saucenao: SauceNao
        :type assert_success: bool
        :return:
        """
        saucenao.api_key = SAUCENAO_API_KEY
        if assert_success:
            result = saucenao.check_file(self.test_jpg)
            self.assertIsInstance(result, list)
        else:
            self.assertRaises(DailyLimitReachedException, saucenao.check_file,
                              self.test_jpg)
示例#5
0
class TestSauceNaoLimits(unittest.TestCase):
    """
    test cases to check the limits for SauceNAO

    currently not covered is the test case: account limit reached, ip limit not reached
    have to add a proxy for this test case to be covered.

    Test cases covered:
     - HTML response type: ip/account limit not reached
     - JSON response type: ip/account limit not reached
     - HTML response type: ip limit reached
     - JSON response type: ip limit reached
    """
    def setUp(self):
        """Constructor for the unittest

        :return:
        """
        self.test_jpg = generate_small_jpg()

        self.saucenao_html = SauceNao(os.getcwd(),
                                      output_type=SauceNao.API_HTML_TYPE,
                                      log_level=logging.DEBUG)
        self.saucenao_json = SauceNao(os.getcwd(),
                                      output_type=SauceNao.API_JSON_TYPE,
                                      log_level=logging.DEBUG)

        self.NOT_IP_LIMIT_NOT_ACCOUNT_LIMIT = [{
            'function': self.check_response_no_api_key,
            'expected_success': True
        }, {
            'function': self.check_response_api_key,
            'expected_success': True
        }]
        self.IP_LIMIT_NOT_ACCOUNT_LIMIT = [{
            'function': self.check_response_no_api_key,
            'expected_success': False
        }, {
            'function': self.check_response_api_key,
            'expected_success': True
        }]
        self.IP_LIMIT_ACCOUNT_LIMIT = [{
            'function': self.check_response_no_api_key,
            'expected_success': False
        }, {
            'function': self.check_response_api_key,
            'expected_success': False
        }]

    def tearDown(self):
        """Destructor for the unittest

        :return:
        """
        os.remove(self.test_jpg)

    def run_tests(self, saucenao: SauceNao, tests):
        """Run the different tests with the given SauceNao instance

        :type saucenao: SauceNao
        :type tests: list|tuple|Generator
        :return:
        """
        for test in tests:
            test_function = test['function']
            test_result = test['expected_success']
            try:
                test_function(saucenao, assert_success=test_result)
            except Exception as e:
                self.fail("{} failed ({}: {})".format(test, type(e), e))

    def test_limits(self):
        """Test the limits of SauceNAO

        :return:
        """
        self.saucenao_html.logger.info(
            'running HTML test, ip limit not reached, account limit not reached'
        )
        self.run_tests(saucenao=self.saucenao_html,
                       tests=self.NOT_IP_LIMIT_NOT_ACCOUNT_LIMIT)
        self.saucenao_html.logger.info(
            'running JSON test, ip limit not reached, account limit not reached'
        )
        self.run_tests(saucenao=self.saucenao_json,
                       tests=self.NOT_IP_LIMIT_NOT_ACCOUNT_LIMIT)

        # now reach the daily limit without API key to reach the IP limit
        if self.saucenao_html.api_key:
            self.saucenao_html.api_key = None

        test_files = [self.test_jpg
                      ] * (SAUCENAO_IP_LIMIT_UNREGISTERED_USER - 2)
        try:
            # check_files returns a generator so we have to improvise here a bit
            for test_file in test_files:
                self.saucenao_html.check_file(test_file)
        except DailyLimitReachedException:
            pass

        # we are at 150 searches -> IP limit unregistered user reached, not basic user
        self.saucenao_html.logger.info(
            'running HTML test, ip limit reached, account limit not reached')
        self.run_tests(saucenao=self.saucenao_html,
                       tests=self.IP_LIMIT_NOT_ACCOUNT_LIMIT)
        self.saucenao_html.logger.info(
            'running JSON test, ip limit reached, account limit not reached')
        self.run_tests(saucenao=self.saucenao_json,
                       tests=self.IP_LIMIT_NOT_ACCOUNT_LIMIT)

        # set API key to reach the account limit
        self.saucenao_html.api_key = SAUCENAO_API_KEY
        test_files = [self.test_jpg
                      ] * (SAUCENAO_IP_LIMIT_BASIC_USER -
                           SAUCENAO_IP_LIMIT_UNREGISTERED_USER - 4)
        try:
            # check_files returns a generator so we have to improvise here a bit
            for test_file in test_files:
                self.saucenao_html.check_file(test_file)
        except DailyLimitReachedException:
            pass

        # we are at 30 searches -> IP limit basic user reached
        self.saucenao_html.logger.info(
            'running HTML test, ip limit reached, account limit reached')
        self.run_tests(saucenao=self.saucenao_html,
                       tests=self.IP_LIMIT_ACCOUNT_LIMIT)
        self.saucenao_html.logger.info(
            'running JSON test, ip limit reached, account limit reached')
        self.run_tests(saucenao=self.saucenao_json,
                       tests=self.IP_LIMIT_ACCOUNT_LIMIT)

    def check_response_no_api_key(self,
                                  saucenao: SauceNao,
                                  assert_success=True):
        """Check the response without an API key
        on assert_success=True expect a dictionary, else an exception

        :type saucenao: SauceNao
        :type assert_success: bool
        :return:
        """
        if assert_success:
            result = saucenao.check_file(self.test_jpg)
            self.assertIsInstance(result, list)
        else:
            self.assertRaises(DailyLimitReachedException, saucenao.check_file,
                              self.test_jpg)

    def check_response_api_key(self, saucenao: SauceNao, assert_success=True):
        """Check the response with an API key
        on assert_success=True expect a dictionary, else an exception

        :type saucenao: SauceNao
        :type assert_success: bool
        :return:
        """
        saucenao.api_key = SAUCENAO_API_KEY
        if assert_success:
            result = saucenao.check_file(self.test_jpg)
            self.assertIsInstance(result, list)
        else:
            self.assertRaises(DailyLimitReachedException, saucenao.check_file,
                              self.test_jpg)
def worker(filepath):
    # initialize saucenao
    saucenao_core = SauceNao(
        directory='directory',
        databases=9,
        # 999 by default, 5 for pixiv, 9 for booru.
        minimum_similarity=65,
        combine_api_types=False,
        api_key=saucenao_api_key,
        exclude_categories='',
        move_to_categories=False,
        use_author_as_category=False,
        output_type=SauceNao.API_JSON_TYPE,
        start_file='',
        log_level=logging.ERROR,
        title_minimum_similarity=90)
    # search image on saucenao
    try:
        result = search(saucenao_core, filepath)
    except requests.exceptions.ConnectionError:
        print("Failed to connect saucenao!")
        return -1
    except saucenao.exceptions.DailyLimitReachedException:
        print("Saucenao daily limit reached! try 1 hour later!")
        return -2
    if (len(result) is 0):
        print('Image not found on danbooru!')
        return 1
    else:
        danbooru_id = result[0]['data']['danbooru_id']
        print('Image Found, ID=' + str(danbooru_id))
        # GET danbooru tag json
        try:
            http = urllib3.PoolManager()
            # disable  https cert check warning
            urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
            url = 'https://danbooru.donmai.us/posts/' + str(
                danbooru_id) + '.json'
            headers = urllib3.util.make_headers(basic_auth=danbooru_login +
                                                ':' + danbooru_api_key)
            r = http.request('GET', url, headers=headers)
            r_data = r.data
            if isinstance(r_data, bytes):
                r_data = str(r_data, 'utf-8')
            tags = json.loads(r_data)['tag_string']
            taglist = tags.split()
        except requests.exceptions.ConnectionError:
            print('failed to GET tag data from danbooru')
            return -1
        # Write XMP Metadata to image
        xmpfile = XMPFiles(file_path=filepath, open_forupdate=True)
        xmp = xmpfile.get_xmp()
        # if image has no xmp data, create one
        if (xmp is None):
            xmp = XMPMeta()
        # write the tags
        for each in taglist:
            # check whether XMP includes 'subject' property,
            # if not, create a new one
            if (not xmp.does_property_exist(consts.XMP_NS_DC, 'subject')):
                xmp.append_array_item(consts.XMP_NS_DC, 'subject', each, {
                    'prop_array_is_ordered': True,
                    'prop_value_is_array': True
                })
            # check whether tag has been written to file
            if (not xmp.does_array_item_exist(consts.XMP_NS_DC, 'subject',
                                              each)):
                xmp.append_array_item(consts.XMP_NS_DC, 'subject', each)
        if (xmpfile.can_put_xmp(xmp)):
            xmpfile.put_xmp(xmp)
            xmpfile.close_file()
            return 0
        else:
            print('Unable to write XMP data!')
            return -1