Esempio n. 1
0
    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]
Esempio n. 2
0
    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)}")
Esempio n. 3
0
    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)}")
Esempio n. 4
0
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)
Esempio n. 5
0
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)
Esempio n. 6
0
#!/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"])
Esempio n. 7
0
#!/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')

Esempio n. 9
0
#!/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',
Esempio n. 10
0
#!/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',