def _probe(self) -> Optional[ValueSet] or List[ValueSet]: self.log.info('Downloading AppStore report...') report_file = os.path.join(self._db_dir, 'report_' + self._vendor + '.csv') # The latest report is always 1 day old report_date = datetime.today() - timedelta(days=1) api = Api(self._key_id, self._key_file, self._issuer_id) try: api.download_sales_and_trends_reports(filters={ 'vendorNumber': self._vendor, 'frequency': 'DAILY', 'reportDate': report_date.strftime('%Y-%m-%d') }, save_to=report_file) except APIError as e: if 'is not available yet' in str(e): # Ignore as the report is simply not yet available return None raise e with open(report_file, encoding='utf-8') as file: lines = file.readlines() if len(lines) < 2: return None sku_map = {} # type: Dict[str, SkuMetrics] headline = lines[0].split('\t') sku_col = self._find_column('SKU', headline) prod_type_col = self._find_column('Product Type Identifier', headline) units_col = self._find_column('Units', headline) dev_proceeds_col = self._find_column('Developer Proceeds', headline) for line in lines[1:]: row = line.split('\t') sku = row[sku_col] if sku not in sku_map: sku_map[sku] = SkuMetrics(sku) sku_metrics = sku_map[sku] units = int(row[units_col]) if ProdTypeIds.is_download(row[prod_type_col]) or \ ProdTypeIds.is_iap(row[prod_type_col]): # Only increment the unit counter if the # item was a download or IAP sku_metrics.units += units # Now create the metrics data = ValueSet(labels=['sku']) for sku, item in sku_map.items(): data.add(Value(item.units, label_values=[sku], name='units')) meta_data = ValueSet() meta_data.add(Value(int(report_date.timestamp()), name='latestUpdate')) return [data, meta_data]
def check_config(self, logger: AirbyteLogger, config_path: str, config: json) -> AirbyteConnectionStatus: """ Tests if the input configuration can be used to successfully connect to the integration e.g: if a provided Stripe API token can be used to connect to the Stripe API. :param logger: Logging object to display debug/info/error to the logs (logs will not be accessible via airbyte UI if they are not passed to this logger) :param config_path: Path to the file containing the configuration json config :param config: Json object containing the configuration of this source, content of this json is as specified in the properties of the spec.json file :return: AirbyteConnectionStatus indicating a Success or Failure """ try: # If an app on the appstore does not support subscriptions or sales, it cannot pull the relevant reports. # However, the way the Appstore API expresses this is not via clear error messages. Instead it expresses it by throwing an unrelated # error, in this case "invalid vendor ID". There is no way to distinguish if this error is due to invalid credentials or due to # the account not supporting this kind of report. So to "check connection" we see if any of the reports can be pulled and if so # return success. If no reports can be pulled we display the exception messages generated for all reports and return failure. api_fields_to_test = { "subscription_event_report": { "reportType": "SUBSCRIPTION_EVENT", "frequency": "DAILY", "reportSubType": "SUMMARY", "version": "1_2", }, "subscriber_report": {"reportType": "SUBSCRIBER", "frequency": "DAILY", "reportSubType": "DETAILED", "version": "1_2"}, "subscription_report": {"reportType": "SUBSCRIPTION", "frequency": "DAILY", "reportSubType": "SUMMARY", "version": "1_2"}, "sales_report": {"reportType": "SALES", "frequency": "DAILY", "reportSubType": "SUMMARY", "version": "1_0"}, } api = Api(config["key_id"], config["key_file"], config["issuer_id"]) stream_to_error = {} for stream, params in api_fields_to_test.items(): test_date = date.today() - timedelta(days=2) report_filters = {"reportDate": test_date.strftime("%Y-%m-%d"), "vendorNumber": f"{config['vendor']}"} report_filters.update(api_fields_to_test[stream]) try: rep_tsv = api.download_sales_and_trends_reports(filters=report_filters) if isinstance(rep_tsv, dict): raise Exception(f"An exception occurred: Received a JSON response instead of" f" the report: {str(rep_tsv)}") except Exception as e: logger.warn(f"Unable to download {stream}: {e}") stream_to_error[stream] = e # All streams have failed if len(stream_to_error.keys()) == api_fields_to_test.keys(): message = "\n".join([f"Unable to access {stream} due to error: {e}" for stream, e in stream_to_error]) return AirbyteConnectionStatus(status=Status.FAILED, message=message) return AirbyteConnectionStatus(status=Status.SUCCEEDED) except Exception as e: logger.warn(e) return AirbyteConnectionStatus(status=Status.FAILED, message=f"An exception occurred: {str(e)}")
def check_config(self, logger: AirbyteLogger, config_path: str, config: json) -> AirbyteConnectionStatus: """ Tests if the input configuration can be used to successfully connect to the integration e.g: if a provided Stripe API token can be used to connect to the Stripe API. :param logger: Logging object to display debug/info/error to the logs (logs will not be accessible via airbyte UI if they are not passed to this logger) :param config_path: Path to the file containing the configuration json config :param config: Json object containing the configuration of this source, content of this json is as specified in the properties of the spec.json file :return: AirbyteConnectionStatus indicating a Success or Failure """ try: # create request fields for testing api_fields_to_test = { "subscription_report": { "reportType": "SUBSCRIPTION", "frequency": "DAILY", "reportSubType": "SUMMARY", "version": "1_2" } } test_date = date.today() - timedelta(days=2) report_filters = { "reportDate": test_date.strftime("%Y-%m-%d"), "vendorNumber": "{}".format(config["vendor"]) } report_filters.update(api_fields_to_test["subscription_report"]) # fetch data from appstore api api = Api(config["key_id"], config["key_file"], config["issuer_id"]) rep_tsv = api.download_sales_and_trends_reports( filters=report_filters) if isinstance(rep_tsv, dict): return AirbyteConnectionStatus( status=Status.FAILED, message= f"An exception occurred: Received a JSON response instead of" f" the report: {str(rep_tsv)}", ) return AirbyteConnectionStatus(status=Status.SUCCEEDED) except Exception as e: logger.warn(e) return AirbyteConnectionStatus( status=Status.FAILED, message=f"An exception occurred: {str(e)}")
def _attempt_download_report( api: Api, report_filters: Dict[str, any]) -> Union[List[Dict], None]: # fetch data from appstore api try: rep_tsv = api.download_sales_and_trends_reports(filters=report_filters) except APIError as e: LOGGER.error(e) return None # parse api response if isinstance(rep_tsv, dict): LOGGER.warning( f"Received a JSON response instead of the report: {rep_tsv}") else: return tsv_to_list(rep_tsv)
def main(): # Parse command line arguments args = utils.parse_args(REQUIRED_CONFIG_KEYS) Context.config = args.config api = Api(Context.config['key_id'], Context.config['key_file'], Context.config['issuer_id']) # If discover flag was passed, run discovery mode and dump output to stdout if args.discover: catalog = discover(api) Context.config = args.config print(json.dumps(catalog, indent=2)) else: Context.tap_start = utils.now() if args.catalog: Context.catalog = args.catalog.to_dict() else: Context.catalog = discover(api) Context.state = args.state sync(api)
#!/usr/bin/env python import sys from appstoreconnect import Api if __name__ == "__main__": key_id = sys.argv[1] key_file = sys.argv[2] issuer_id = sys.argv[3] api = Api(key_id, key_file, issuer_id) apps = api.apps() for app in apps["data"]: print(app["attributes"]["name"])
#!/usr/bin/env python import sys from appstoreconnect import Api from appstoreconnect import AppStoreState if __name__ == "__main__": key_id = sys.argv[1] key_file = sys.argv[2] issuer_id = sys.argv[3] api = Api(key_id, key_file, issuer_id) app = api.app_for_bundleId("com.orange.fr.orangeetmoi") app_id = app["data"][0]["id"] appstoreversions = api.appstoreversions_for_app(app_id) appstoreversion_id = appstoreversions["data"][0]["id"] #appstorestate = appstoreversions["data"][0]["attributes"]["appStoreState"] #print(appstoreversions["data"][0]) #builds = api.builds_for_app_and_version_and_prerelease_version_version(app_id, "1.0.0", "4") #build_id = builds["data"][0]["id"] #icons = api.build_icons_for_build(build_id) #if appstorestate in AppStoreState.editableStates(): #r = api.update_idfaUse_for_appstoreversion(appstoreversion_id, True) #print(r) r = api.idfadeclaration_for_appstoreversion(appstoreversion_id) print(r) r = api.update_idfaUse_for_appstoreversion(appstoreversion_id, False, True) print(r)
#!/usr/bin/env python import sys from appstoreconnect import Api if __name__ == "__main__": key_id = sys.argv[1] # 479L849VK2 key_file = sys.argv[2] issuer_id = sys.argv[3] # 69b7a93b-1e01-4c97-959f-e124571c5fbd api = Api(key_id, key_file, issuer_id) # list all apps apps = api.list_devices() for app in apps: print(app.name, app.udid) # apps = api.list_apps() # for app in apps: # print(app.name, app.sku) # filter apps # apps = api.list_apps(filters={'sku': 'DINORUSH', 'name': 'Dino Rush'}) # print("%d apps found" % len(apps)) # # download sales report # api.download_sales_and_trends_reports( # filters={'vendorNumber': '123456789', 'frequency': 'WEEKLY', 'reportDate': '2019-06-09'}, save_to='report.csv') # # download finance report # api.download_finance_reports(filters={'vendorNumber': '123456789', 'reportDate': '2019-06'}, save_to='finance.csv')
#!/usr/bin/env python import sys from appstoreconnect import Api if __name__ == "__main__": key_id = sys.argv[1] key_file = sys.argv[2] issuer_id = sys.argv[3] api = Api(key_id, key_file, issuer_id) # list all apps apps = api.list_apps() for app in apps: print(app.name, app.sku) # filter apps apps = api.list_apps(filters={'sku': 'DINORUSH', 'name': 'Dino Rush'}) print("%d apps found" % len(apps)) # download sales report api.download_sales_and_trends_reports(filters={ 'vendorNumber': '123456789', 'frequency': 'WEEKLY', 'reportDate': '2019-06-09' }, save_to='report.csv') # download finance report api.download_finance_reports(filters={ 'vendorNumber': '123456789',
#!/usr/bin/env python import sys from appstoreconnect import Api, UserRole if __name__ == "__main__": key_id = sys.argv[1] key_file = sys.argv[2] issuer_id = sys.argv[3] api = Api(key_id, key_file, issuer_id) # list all apps apps = api.list_apps() for app in apps: print(app.name, app.sku) # filter apps apps = api.list_apps(filters={'sku': 'DINORUSH', 'name': 'Dino Rush'}) print("%d apps found" % len(apps)) # modify a user user = api.list_users(filters={'username': '******'})[0] api.modify_user_account(user, roles=[ UserRole.FINANCE, UserRole.APP_MANAGER, UserRole.ACCESS_TO_REPORTS ]) # download sales report api.download_sales_and_trends_reports(filters={ 'vendorNumber': '123456789',