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 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
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()
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)
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