예제 #1
0
def process_app_pay_receipt(receipt, shared_secret=None) -> Tuple[bool, dict]:
    bundle_id = os.environ['BUNDLE_ID']
    # if True, automatically query sandbox endpoint
    # if validation fails on production endpoint
    if is_true(os.environ['AUTO_RETRY_WRONG_ENV_REQUEST']):
        auto_retry_wrong_env_request = True
    else:
        auto_retry_wrong_env_request = False
    validator = AppStoreValidator(
        bundle_id=bundle_id,
        sandbox=is_true(os.environ['RECEIPT_SANDBOX']),
        auto_retry_wrong_env_request=auto_retry_wrong_env_request,
    )
    try:
        # if True, include only the latest renewal transaction
        exclude_old_transactions = False
        logging.debug("Validating AppStore Receipt:")
        validation_result: Dict[Any, Any] = validator.validate(
            receipt=receipt,
            shared_secret=shared_secret,
            exclude_old_transactions=exclude_old_transactions)
        logging.debug(f'Validation Result: {validation_result}')
    except InAppPyValidationError as ex:
        # handle validation error
        # contains actual response from AppStore service.
        response_from_apple = ex.raw_response
        logging.debug(f"validation failure: {response_from_apple}")
        return (False, response_from_apple)

    return (True, validation_result)
예제 #2
0
def main(event, context):
    stage = os.environ['STAGE']
    body = json.loads(event.get('body', {}))

    if is_true(body.get('debug', '')):
        configure_logging(level="DEBUG")

    logging.debug(f'entry_payment_google stage:{stage}')
    logging.debug(f'os.environ: {os.environ}')
    logging.debug(f'event: {event}')
    logging.debug(f'context: {context}')

    logging.debug(f'body: {body}')
    #receipt     = body.get('receipt', '')
    #bundle_id   = body.get('bundle_id', '')
    account_id = body.get('account_id', '')
    verify_receipt = True
    # todo: add optional existing account

    if os.environ['STAGE'] == 'dev':
        verify_receipt = is_true(body.get('verify_receipt', 'True'))

    if os.environ['STAGE'] != 'dev':
        if body.get('verify_receipt', None) is not None:
            return response(402, {'msg': 'invalid_dev_param'})

    GOOGLE_SERVICE_ACCOUNT_KEY_FILE = get_secret(
        'ORCHID_GOOGLE_SERVICE_ACCOUNT2')
    logging.debug(f'{GOOGLE_SERVICE_ACCOUNT_KEY_FILE}')

    GOOGLE_SERVICE_ACCOUNT_KEY = json.loads(GOOGLE_SERVICE_ACCOUNT_KEY_FILE)

    purchase_token = body.get('receipt', '')
    product_id = body.get('product_id', '')
    bundle_id = body.get('bundle_id', 'net.orchid.Orchid')

    msg, receipt_hash, total_usd = verify_(GOOGLE_SERVICE_ACCOUNT_KEY,
                                           purchase_token, product_id,
                                           bundle_id)

    if ((account_id is None) or (account_id == '')):
        account_id = receipt_hash

    if (msg == "success"):
        logging.debug(f'conditional writing receipt with hash: {receipt_hash}')
        try:
            w3_generic.dynamodb_cwrite1(os.environ['RECEIPT_TABLE_NAME'],
                                        'receipt', receipt_hash)
        except Exception as e:
            logging.info(f'writing receipt exception: {str(e)} ')
            return response(403, {'msg': 'Receipt already redeemed'})
        w3_generic.credit_account_balance(account_id, total_usd)
        return response(200, {
            'msg': msg,
            'account_id': account_id,
            'total_usd': total_usd
        })
    else:
        return response(402, {'msg': msg})
예제 #3
0
    def test_is_true(self):
        trues = (1, "True", "true", "TRUE", "t", "T")
        for t in trues:
            res = utils.is_true(t)
            self.assertTrue(res)

        falses = (0, "False", "FALSE", "false", "f", "F")
        for f in falses:
            res = utils.is_true(f)
            self.assertFalse(res)
예제 #4
0
def main(event, context):
    stage = os.environ['STAGE']
    body  = json.loads(event.get('body', {}))

    if is_true(body.get('debug', '')):
        configure_logging(level="DEBUG")

    logging.info(f'entry_send_raw() stage:{stage}')
    logging.info(f'event: {event}')
    logging.info(f'context: {context}')
    logging.info(f'body: {body}')

    txn_s         = body.get('txn', '')
    sig         = body.get('sig', '')
    if (sig != ''):
        if (verify_txn_sig(txn_s,sig) == False):
            return response(409,{'msg':'Signature verification failure','txnhash':0,'cost_usd':0.0})
    txn = json.loads(txn_s)

    chainId = txn.get('chainId',1)
    w3wsmap = w3_generic.get_w3wsock_providers()

    txnhash,cost_usd,msg = new_txn(w3wsmap,txn)
    logging.info(f'send_raw txnhash({txnhash}) cost_usd({cost_usd}) msg({msg}) ')

    if (msg == 'success'):
        return response(200,{'msg':msg,'txnhash':txnhash,'cost_usd':cost_usd})
    else:
        return response(401,{'msg':msg,'txnhash':0,'cost_usd':0.0})
예제 #5
0
def get_oxt_balance(address=get_secret(key=os.environ['PAC_FUNDER_PUBKEY_SECRET'])) -> float:
    token_addr = w3.toChecksumAddress(os.environ['TOKEN'])
    token_contract = w3.eth.contract(
        abi=token_abi,
        address=token_addr,
    )
    token_name = get_token_name(token_addr)
    token_symbol = get_token_symbol(token_addr)
    token_decimals = get_token_decimals(token_addr)
    DECIMALS = 10 ** token_decimals
    raw_balance = token_contract.functions.balanceOf(address).call()
    balance = raw_balance / DECIMALS
    logging.info(
        f"Balance of {address}: {balance} {token_name} ({token_symbol})")
    if is_true(os.environ.get('ENABLE_MONITORING', '')):
        lambda_metric(
            f"orchid.pac.balance.{token_symbol.lower()}",
            balance,
            tags=[
                f'account:{address}',
                f'token_name:{token_name}',
                f'token_symbol:{token_symbol}',
                f'token_decimals:{token_decimals}',
            ]
        )
    return balance
예제 #6
0
def main(event, context):
    stage = os.environ['STAGE']
    body = json.loads(event.get('body', {}))

    if is_true(body.get('debug', '')):
        configure_logging(level="DEBUG")

    logging.debug(f'entry_send_raw() stage:{stage}')
    logging.debug(f'event: {event}')
    logging.debug(f'context: {context}')
    logging.debug(f'body: {body}')

    try:
        #W3WSock     = body.get('W3WSock', '')
        W3WSock = os.environ['WEB3_WEBSOCKET']
        txn = body.get('txn', '')
        account_id = body.get('account_id', '')

        txnhash, cost_usd, msg = w3_generic.send_raw(W3WSock, txn, account_id)

        logging.debug(
            f'send_raw txnhash({txnhash}) cost_usd({cost_usd}) msg({msg}) ')
    except ValueError as e:
        msg = str(e)
    except:
        msg = sys.exc_info()[0]

    if (msg == 'success'):
        return response_success(txnhash, cost_usd)
    else:
        return response_error(msg)
예제 #7
0
def main(event, context):
    stage = os.environ['STAGE']

    logging.debug(f'verify stage:{stage}')
    logging.debug(f'event: {event}')

    body = json.loads(event.get('body', {}))
    logging.debug(f'body: {body}')

    if is_true(body.get('debug', '')):
        configure_logging(level="DEBUG")

    msg = body.get('msg', '')
    sig = body.get('sig', '')

    verified = verifyMessage(message_text=msg, signed_message=sig)

    resp_body = {
        'message_text': msg,
        'signed_message': sig,
        'verified': verified,
    }

    response = {
        "isBase64Encoded": False,
        "statusCode": 200,
        "headers": {},
        "body": json.dumps(resp_body)
    }
    logging.debug(f'verify response: {response}')
    return response
예제 #8
0
파일: metrics.py 프로젝트: baajur/orchid
def metric(metric_name: str, value: float, timestamp=None, tags=None):
    if is_true(os.environ.get('ENABLE_MONITORING', '')):
        lambda_metric(
            metric_name=metric_name,
            value=value,
            timestamp=timestamp,
            tags=tags,
        )
예제 #9
0
def api_list_users():
    details = request.args.get('details')
    all_users = praat.User.query.all()
    if utils.is_true(details):
        res = list(u.details() for u in all_users)
    else:
        res = list(u.summary() for u in all_users)
    return jsonify(res)
예제 #10
0
def api_list_groups():
    details = request.args.get('details')
    all_groups = praat.Group.query.all()
    if utils.is_true(details):
        res = list(gp.details() for gp in all_groups)
    else:
        res = list(gp.summary() for gp in all_groups)
    return jsonify(res)
예제 #11
0
def main(event, context):
    stage = os.environ['STAGE']
    body = json.loads(event.get('body', {}))

    if is_true(body.get('debug', '')):
        configure_logging(level="DEBUG")

    logging.debug(f'refund_failed_txn() stage:{stage}')
    logging.debug(f'event: {event}')
    logging.debug(f'context: {context}')

    logging.debug(f'body: {body}')
    receipt     = body.get('receipt', '')
    #bundle_id   = body.get('bundle_id', '')
    account_id  = body.get('account_id', '')
    product_id  = body.get('product_id', None)
    verify_receipt = True
    # todo: add optional existing account

    if os.environ['STAGE'] == 'dev':
        verify_receipt = is_true(body.get('verify_receipt', 'True'))

    if os.environ['STAGE'] != 'dev':
        if body.get('verify_receipt'):
            return response(444,{'msg':'invalid_dev_param'})

    msg, receipt_hash, total_usd = payments_apple.handle_receipt(receipt, product_id, stage, verify_receipt)

    if ((account_id is None) or (account_id == '')):
        account_id = receipt_hash

    if (msg == "success"):
        logging.debug(f'conditional writing receipt with hash: {receipt_hash}')
        try:
            w3_generic.dynamodb_cwrite1(os.environ['RECEIPT_TABLE_NAME'], 'receipt', receipt_hash )
        except Exception as e:
            logging.info(f'writing receipt exception: {str(e)} ')
            return response(403,{'msg':f'Receipt {receipt_hash} already redeemed'})
        w3_generic.credit_account_balance(account_id, total_usd)
        return response(200,{'msg':msg,'account_id':account_id,'total_usd':total_usd})
    else:
        return response(402,{'msg':msg})
예제 #12
0
def do_create_nginx(options):
    if not utils.is_true('create_nginx', options['nginx']):
        return False

    config_path = options['system']['nginx_config_path']
    content = utils.get_config_content(config_path)
    content = get_prepared_content(content, options, 'nginx')

    httpd_path = options['system']['nginx_path']
    file_name = options['nginx']['site_name'] + '.conf'
    full_file_path = httpd_path + file_name

    utils.create_file(full_file_path, content)
    utils.success_msg("Nginx File was Created.")
예제 #13
0
def do_create_hosts(options):
    if not utils.is_true('add_hosts', options['default']):
        return False

    file_hosts_path = options['system']['file_hosts_path']
    if not os.path.isfile(file_hosts_path):
        raise Exception('File Hosts Not Found')

    host_ip = options['system']['hosts_ip']
    string = "\n" + host_ip + " " + options['default']['site_name']
    #add conditions if record exists
    file = open(file_hosts_path, 'a')
    file.write(string)
    file.close()

    utils.success_msg("Record in Hosts was Added.")
예제 #14
0
    def __init__(self, meta_configs, appname, use_kv_store=False):
        """
        @meta_configs: dict like and contains checkpoint_dir, session_key,
        server_uri etc
        """

        self._meta_configs = meta_configs
        self._appname = appname
        self._states_cache = {}
        self._kv_client = None
        if utils.is_true(use_kv_store):
            self._state_collection = "states"
            self._kv_client = kvc.KVClient(meta_configs["server_uri"],
                                           meta_configs["session_key"])
            kvc.create_collection(self._kv_client, self._state_collection,
                                  self._appname)
            self._pop_states_cache()
예제 #15
0
    def __init__(self, meta_configs, appname, use_kv_store=False):
        """
        @meta_configs: dict like and contains checkpoint_dir, session_key,
        server_uri etc
        """

        self._meta_configs = meta_configs
        self._appname = appname
        self._states_cache = {}
        self._kv_client = None
        if utils.is_true(use_kv_store):
            self._state_collection = "states"
            self._kv_client = kvc.KVClient(meta_configs["server_uri"],
                                           meta_configs["session_key"])
            kvc.create_collection(self._kv_client, self._state_collection,
                                  self._appname)
            self._pop_states_cache()
예제 #16
0
def get_eth_balance(address=get_secret(
    key=os.environ['PAC_FUNDER_PUBKEY_SECRET'])) -> float:
    token_name = 'Ethereum'
    token_symbol = 'ETH'
    token_decimals = 18
    DECIMALS = 10**token_decimals
    raw_balance = w3.eth.getBalance(address)
    balance = raw_balance / DECIMALS
    logging.info(
        f"Balance of {address}: {balance} {token_name} ({token_symbol})")
    if is_true(os.environ.get('ENABLE_MONITORING', '')):
        lambda_metric(f"orchid.pac.balance.{token_symbol.lower()}",
                      balance,
                      tags=[
                          f'account:{address}',
                          f'token_name:{token_name}',
                          f'token_symbol:{token_symbol}',
                          f'token_decimals:{token_decimals}',
                      ])
    return balance
예제 #17
0
def main(event, context):
    stage = os.environ['STAGE']
    body = json.loads(event.get('body', {}))

    if is_true(body.get('debug', '')):
        configure_logging(level="DEBUG")

    logging.debug(f'recycle() stage:{stage}')
    logging.debug(f'event: {event}')
    logging.debug(f'context: {context}')
    logging.debug(f'body: {body}')
    funder = toChecksumAddress(address=body.get('funder', ''))
    signer = toChecksumAddress(address=body.get('signer', ''))
    password = body.get('password', '')

    if password != get_secret(key=os.environ['RECYCLE_KEY']):
        return incorrect_password()

    pac_funder = get_secret(key=os.environ['PAC_FUNDER_PUBKEY_SECRET'])

    if funder != pac_funder:
        return invalid_funder(funder, pac_funder)

    funder_keys = keys(funder)
    if signer == '' or signer not in funder_keys:
        return invalid_signer(signer)

    amount, escrow, unlock = look(funder, signer)

    amount_threshold = float("inf")
    escrow_threshold = float("inf")

    if amount > amount_threshold:
        return amount_too_high(amount, amount_threshold)

    if escrow > escrow_threshold:
        return escrow_too_high(escrow, escrow_threshold)

    store_account(funder, signer, unlock)
    return account_queued_response()
예제 #18
0
def main(event, context):
    stage = os.environ['STAGE']
    body = json.loads(event.get('body', {}))

    if is_true(body.get('debug', '')):
        configure_logging(level="DEBUG")

    logging.debug(f'refund_failed_txn() stage:{stage}')
    logging.debug(f'event: {event}')
    logging.debug(f'context: {context}')
    logging.debug(f'body: {body}')


    W3WSock     = body.get('W3WSock', '')
    txnhash     = body.get('txnhash', '')
    receiptHash = body.get('receiptHash', '')

    msg  = w3_generic.refund_failed_txn(W3WSock,txnhash,receiptHash)

    if (msg == "success"):
        return response_success(txnhash)
    else:
        return response_error(msg)
예제 #19
0
def do_create_site(options):
    if not utils.is_true('create_test_folder', options['default']):
        return False

    if not os.path.isdir(options['default']['site_path']):
        utils.error_msg('Path to Folder Site Not Found')
        return False

    site_folder_path = options['default']['site_path'] + options['default'][
        'site_name']

    if os.path.isdir(site_folder_path):
        utils.error_msg('Site Folder is Exist')
        return False

    os.makedirs(site_folder_path)

    template_path = options['system']['template_page_path']
    content = utils.get_config_content(template_path)

    site_folder_path = site_folder_path + "/index.html"
    utils.create_file(site_folder_path, content)

    utils.success_msg("Site Folder was Created.")
예제 #20
0
def generic_audio_ops(user, group, method, audio=None, params=None):
    if group is None:
        return "Group does not exist"
    storage_svc = get_storage_service(praat.app.config)
    if method == 'GET':
        #g_info = group.details()
        #return jsonify(g_info['details']['audios'])
        audios = []
        for audio in group.audios:
            info = audio.summary()
            if utils.is_true(params.get('show_versions')):
                info['versions'] = storage_svc.show_versions(audio.id)
            audios.append(info)
        resp = {"status": "success", "audios": audios}
        print resp
        return jsonify(resp)

    if not audio or not audio.filename:
        # If no audio file, stop
        status = "No audio file"
        audioName = ""
    elif not utils.isSound(audio.filename):
        # Stop if uploaded file is not a audio
        status = "Unknown file type"
        audioName = audio.filename
    else:
        audioName = audio.filename
        data = audio.read()
        key_seed = group.id + audioName
        key = utils.generate_id(group.id + audioName)
        attrs = {
            'created_by': user.email,
        }
        audioObj = praat.Audio.query.get(key)
        retval = storage_svc.put(key, data, attrs)
        # save waveform
        temp_dir = '/tmp/waveform' + key + retval['version'] + '/'
        waveform_name = key + retval['version'] + '.png'
        utils.mkdir_p(temp_dir)
        with open(temp_dir + audioName, 'w') as fp:
            fp.write(data)
        script = praat._scripts_dir + 'drawWaveV2'
        params = [temp_dir + audioName, temp_dir + waveform_name]
        praat.runScript(script, params)
        with open(temp_dir + waveform_name, 'r') as fp:
            data = fp.read()
            attrs = {'name': audioName}
            attrs.update(retval)
            storage_svc.put(waveform_name, data, attrs)
        utils.rm_rf(temp_dir)

        if audioObj is None:
            print 'Creating new audio file'
            audioObj = praat.Audio(audioName, user, group, key_seed)
            praat.db_session.add(audioObj)
            praat.db_session.commit()
        else:
            print audioObj.summary()
            audioObj.updated_at = datetime.datetime.utcnow()
            praat.db_session.commit()
            print 'Updating existing audio file'
        status = "Success"

    result = {
        "status": status,
        "audio": audioName
    }
    #return jsonify(result)
    return redirect('/?context=workspace')
예제 #21
0
def annotation_ops(audio, vid=None):
    user = g.user
    audio_obj = praat.Audio.query.get(audio)
    if audio_obj is None:
        return jsonify({"status": "fail", "message": "Audio file does not exist"})
    storage_svc = get_storage_service(praat.app.config)
    if request.method == 'GET':
        anns = []
        for annotation in audio_obj.annotations:
            summary = annotation.summary()
            if vid and vid != annotation.audio_version:
                continue
            if utils.is_true(request.args.get('show_versions')):
                summary['versions'] = storage_svc.show_versions(annotation.id)
            anns.append(summary)
        resp = {"status": "success", 'annotations': anns}
        return jsonify(resp)
    payload = request.json
    audio_version = vid or payload.get('audio_version')
    all_versions = storage_svc.show_versions(audio_obj.id)
    if audio_version is None:
        if len(all_versions) > 0:
            audio_version = all_versions[0]['version']
        else:
            return jsonify({"status": "fail", "message": "unable to find any version of audio"})
    else:
        version_exists = False
        for v in all_versions:
            if v['version'] == audio_version:
                version_exists = True
                break
        if not version_exists:
            return jsonify({"status": "fail", "message": "Audio version " + audio_version + " does not exist"})
    # Annotation key is a combinatiom of audio id, audio version, and annotation name
    name = payload['name']
    a_key_seed = "%s:%s:%s" % (audio, audio_version, name)
    # create or update an annotation object
    start_time = payload['startTime']
    end_time = payload['endTime']
    if float(start_time) < 0 or float(end_time) < float(start_time):
        return jsonify({"status": "fail", "message": "Invalid annotation start/end time"})
    annotation_obj = praat.AudioAnnotation.query.get(utils.generate_id(a_key_seed))
    if annotation_obj is None:
        print "Creating new Annotation"
        annotation_obj = praat.AudioAnnotation(name, audio, audio_version, start_time, end_time, a_key_seed)
        praat.db_session.add(annotation_obj)
        praat.db_session.commit()
    else:
        if annotation_obj.start_time != start_time or annotation_obj.end_time != end_time:
            return jsonify({"status":"fail", "message": "Inconsistent start time or end time for annotation " + name})
        annotation_obj.updated_at = datetime.datetime.utcnow()
        praat.db_session.commit()

    # save annotation details in annotation version
    attributes = {
        'created_by': user.email,
    }
    contents = {
        'commitMessage': payload.get('commitMessage', ''),
        'tierOne': payload.get('tierOne', ''),
        'tierTwo': payload.get('tierTwo', ''),
        'tierThree': payload.get('tierThree', ''),
    }
    storage_svc.put(annotation_obj.id, json.dumps(contents), attributes)
    return jsonify({"status": "success", "summary": annotation_obj.summary()})
예제 #22
0
파일: townguide.py 프로젝트: hixi/townguide
    def populateDB(self):
        """
        Download the required data from the OSM server, and populate the
        postresql database with it.
        31dec2009  GJ  ORIGINAL VERSION
        """
        print "populateDB"
        
        #Convert the lat/long origin into mercator projection metres.
        prj = mapnik.Projection(self.srs)
        c0 = prj.forward(mapnik.Coord(self.lon,self.lat))

        c0.x += self.map_size_x * self.tilesize
        c0.y += self.map_size_y * self.tilesize

        c1 = prj.inverse(c0)
        lon=c1.x
        lat=c1.y
        print "before = (%f,%f)" % (self.lon,self.lat)
        print c1
        print "after  = (%f,%f)" % (lon,lat)

        if is_true(self.preferences_list['xapi']):
            # XAPI Server
            print 'Using OSM XAPI Server for data download'
            url="http://www.openstreetmap.org/api/0.6/map?bbox=%f,%f,%f,%f" %\
                 (self.lon,self.lat,lon,lat)
            # url="http://www.informationfreeway.org/api/0.6/map?bbox=%f,%f,%f,%f" %\
            #      (self.lon,self.lat,lon,lat)
        else:
            # Live OSM Server
            print 'Using live OSM Server for data download'
            url="http://www.openstreetmap.org/api/0.6/map?bbox=%f,%f,%f,%f" %\
                 (self.lon,self.lat,lon,lat)

        osmFile = "%s/townguide.osm" % (self.preferences_list['outdir'])

        os.system("wget %s -O %s" % (url,osmFile))

        if os.path.exists(osmFile):
            try:
                print 'Importing data into postgresql database....'
                osm2pgsqlStr = "osm2pgsql -m -S %s/%s -d %s -a %s" %\
                           (self.preferences_list['datadir'],
                            "default.style",
                            self.preferences_list['dbname'],
                            osmFile)
                print "Calling osm2pgsql with: %s" % osm2pgsqlStr
                retval = os.system(osm2pgsqlStr)
                if (retval==0):
                    print 'Data import complete.'
                else:
                    print 'osm2pgsql returned %d - exiting' % retval
                    # system.exit(-1)
            except:
                print "Exception Occurred running osm2pgsql"
                system.exit(-1)
        else:
            print "ERROR:  Failed to download OSM data"
            print "Aborting...."
            system.exit(-1)
예제 #23
0
파일: townguide.py 프로젝트: hixi/townguide
    def getAmenities(self):
        """Extract the required map features from the database
        for each map square and store the data in the 'amenities'
        dictionary.
        An index of the street names is stored in self.streetIndex dictionary.
        
        FIXME:  This is very inefficient - it queries the database
        for the bounding box and each required feature in turn.
        It sould be more efficient to get all of the data in the bounding
        box then query that, but I haven't done it.

        01oct2009 GJ ORIGINAL VERSION
        04oct2009  GJ Added use of expandWhereClause to allow grouping
                      of different key values under the same heading
                      in the features page.
        11oct2009 GJ  Added support for areas (polygons) as well as nodes.
        """
        # Extract the data for each 1km square.
        if (self.debug): print "getAmenities()"
        c0 = self.c0                    # lon, lat
        streetList = {}
        streetIndexSorted = {}
        print c0

        # Get all the features and then create clusters ===
        if is_true(self.preferences_list['clusters']):
            print "........... Trying out something .........."
            tilesize = self.preferences_list['tilesize']
            map_width = self.map_size_x
            map_height = self.preferences_list['map_size_y']

            min_lon = c0.x
            min_lat = c0.y
            max_lon = c0.x + (tilesize * map_width)
            max_lat = c0.y + (tilesize * map_height)

            # Experimental cluster markers
            # tolerance to become a cluster should change according to the zooming factor
            tolerance = 20 * self.map_size_x

            # k-means first iteration
            clusters = {}
            if HAS_MAPNIK2:
                bbox = mapnik.Box2d(min_lon, min_lat, max_lon, max_lat)
            else:
                bbox = mapnik.Envelope(min_lon, min_lat, max_lon, max_lat)

            for featureStr in self.features:
                title,wc = self.expandWhereClause(featureStr)
                print "::::", title, wc
                feature = title
                if self.debug: print "Extracting feature %s using %s." %\
                   (feature,featureStr)            
                pois = self.getBBContents(bbox,wc)

                # poi[6]: lat
                # poi[7]: lon
                print "Current Contents for ", featureStr, pois

                for poi in pois:
                    if not len(self.clusters) > 0:
                        print "POI:", poi
                        c = Cluster(feature)
                        c.add_poi(poi)
                        self.clusters.append(c)
                        print "Created the First cluster: ", c.centroid
                    else:
                        # Look for the custer where the POI should be inserted
                        # by noticing the difference with that cluster's centroid

                        # If the distance to that cluster's centroid is less than
                        # the tolerance it will be inserted there.                    
                        # This should work like a non-optimal first iteration of k-means
                        CLUSTER_FOUND = False
                        for (scounter, cluster) in enumerate(self.clusters):
                            distance = cluster.distance_from_poi(poi)
                            print "This cluster", cluster.pois
                            print distance
                            if distance < tolerance:
                                # Add POI to cluster
                                print "--- POI should get in this cluster"
                                cluster.add_poi(poi)
                                CLUSTER_FOUND = True
                                print "BREAK!!!"
                                break
                        if not CLUSTER_FOUND:
                            print "_____ Could not find a suited cluster _____"
                            # Create a new cluster
                            print "------ Creating a new cluster for this poi"
                            new_cluster = Cluster(feature)
                            new_cluster.add_poi(poi)
                            self.clusters.append(new_cluster)

            for kluster in self.clusters:
                print len(kluster.pois), vars(kluster)

            print "............................................."
            #=========================================================== 

        for tx in range(0,self.map_size_x):
            minx = c0.x + self.preferences_list['tilesize'] * tx
            for ty in range(0,self.preferences_list['map_size_y']):
                # sys.stdout.write("%s" % self.cellLabel(tx,ty))
                # sys.stdout.flush()
                print "%s " % self.cellLabel(tx,ty)
                miny = c0.y + self.preferences_list['tilesize'] * ty

                if HAS_MAPNIK2:
                    bbox = mapnik.Box2d(minx,
                                        miny,
                                        minx + self.preferences_list['tilesize'],
                                        miny + self.preferences_list['tilesize'])
                else:
                    bbox = mapnik.Envelope(minx,
                                           miny,
                                           minx + self.preferences_list['tilesize'],
                                           miny + self.preferences_list['tilesize'])
                
                fname = "image_%02d_%02d.png" % (tx,ty)
                #if self.debug: print bbox

                ########################################################
                # Extract points of interest into amenities dictionary #
                ########################################################
                
                for featureStr in self.features:
                    title,wc = self.expandWhereClause(featureStr)
                    # print "::::", title, wc
                    feature = title
                    if self.debug: print "Extracting feature %s using %s." %\
                       (feature,featureStr)
                    
                    # FIXME: This needs to be optimized for clustering
                    pois = self.getBBContents(bbox,wc)
                    for poi in pois:
                        if feature in self.amenities:
                            self.amenities[feature].append((tx,ty,poi))
                        else:
                            self.amenities[feature]=[(tx,ty,poi)]
                    # print self.amenities
                    # print len(self.amenities)
                    # print "__________________________________"

                ##############################################
                # Extract all of the streetnames in the cell #
                ##############################################
                bbStreets = self.getBBStreets(bbox)
                streetList[self.cellLabel(tx,ty)] = bbStreets

                # Render a high resolution tile of this cell.
                #fname = "%s/%s.png" % (self.outdir,self.cellLabel(tx,ty))
                #self.drawTile(bbox,1000,1000,fname)


        #####################################################
        # Sort the amenities list to remove duplicates      #
        # The result is self.amenitiesSorted which is a     #
        # dictionary of features.  Each feature contains    #
        # a dictionary of amenity names.   Each amenity     #
        # name entry contains a list of cell IDs as strings #
        #                                                   #
        #####################################################
        for feature in self.amenities.keys():
            # poi = (tx,ty,(id, name, operator))
            # example:
            # (0, 0, (663528594, 'Tangerine', None, 'restaurant', None, None, 4546182.5512522003, -13628929.6157306))
            for poi in self.amenities[feature]:
                cellId = self.cellLabel(poi[0],poi[1])
                osm_id = poi[2][0]      # 663528594
                name = poi[2][1]        # 'Tangerine'
                operator = poi[2][2]    # Company that runs the place
                amenityVal = poi[2][3]  # Type of amenity
                shopVal = poi[2][4]      
                landuse = poi[2][5]
                if name == None:
                    if amenityVal == None:
                        if shopVal == None:
                            if landuse == None:
                                name = "Unidentified thing - osm_id=%d" % osm_id
                            else:
                                name = "Unnamed %s" % landuse
                        else:
                            name = "Unnamed %s" % shopVal
                    else:
                        name = "Unnamed %s" % amenityVal
                        
                print "%s,  %s, %s" % (feature, name, cellId)
                # Entertainment,  Castro Theater,  A1
                if not feature in self.amenitiesSorted:
                    print "creating dictionary for feature %s" % feature
                    self.amenitiesSorted[feature]={}
                if name in self.amenitiesSorted[feature]:
                    print "dictionary %s already exists in feature %s" % (name,feature)
                    if not cellId in self.amenitiesSorted[feature][name]:
                        print "appending cellid"
                        self.amenitiesSorted[feature][name].append(cellId)
                    else:
                        print "skipping duplicate feature %s %s in %s\n" % (feature,name,cellId)
                else:
                    print "adding cell id to list"
                    self.amenitiesSorted[feature][name] = [cellId]
                    print "self.amenitiesSorted=", self.amenitiesSorted[feature][name]


        #########################################################
        # Sort the street index into a simple dictionary of     #
        # street name mapped to a list of which cells contain   #
        # parts of the street of that name                      #
        #########################################################

        # In the following, streetList is a dictionary with keys which
        # are cell IDs - the contents of the dictionary is a list of all
        # of the streets in a given cell.

        # StreeetIndexSorted is a dictionary with streetnames as the keys
        # The contents is a list of all of the cells that contain a way
        # of the given name.

        # self.StreetIndex is a tidied up version of StreetIndexSorted - the
        # contents is a displayable string showing which cells contain the
        # given street name.
        

        # Now we need to sort the street index so that we have a schedule
        # of streets identifying which cells the street is in.
        for cell in streetList:
            for street in streetList[cell]:
                streetName = street[1]
                if streetName != 'None':
                    if streetName in streetIndexSorted:
                        # Avoid multiple entries of the same cell for a
                        #   given street name - if it exists in the list,
                        # reject it, otherwise add it to the list..
                        try:
                            i = streetIndexSorted[streetName].index(cell)
                            if self.debug:
                                print "Rejected Duplicate Entry ",\
                                      streetName,cell,i
                        except:
                            streetIndexSorted[streetName].append(cell)
                    else:
                        streetIndexSorted[streetName] = [cell]


        streets = streetIndexSorted.keys()
        streets.sort()
        for street in streets:
            cellstr=""
            first = True
            cells = streetIndexSorted[street]
            cells.sort()
            for cell in cells:
                if first==True:
                    cellstr = "%s" % cell
                    first=False
                else:
                    cellstr = "%s, %s" % (cellstr,cell)
            self.streetIndex[street]=cellstr
예제 #24
0
파일: townguide.py 프로젝트: hixi/townguide
    def drawOverviewMap(self,outdir='',addFeatures=False):
        """Draws the overview map of the full area requested and
        adds a grid with row and column identifiers to the map image.
        29sep2009  GJ ORIGINAL VERSION
        01jan2010  Added option to add feature markers to map.
        17oct2010  GJ  Separated grid and features out into separate
                       overlay plugins.
        """
        # First draw the basic map using mapnik.
        fname = "%s/overview.png" % outdir

        if self.debug: print "Drawing Overview Map - fname=",fname

        c0 = self.c0

        if HAS_MAPNIK2:
            bbox = mapnik.Box2d(c0.x,
                                c0.y,
                                c0.x + self.preferences_list['tilesize'] * \
                                    self.preferences_list['map_size_x'],
                                c0.y + self.preferences_list['tilesize'] * \
                                    self.preferences_list['map_size_y'])
        else:
            bbox = mapnik.Envelope(c0.x,
                                   c0.y,
                                   c0.x + self.preferences_list['tilesize'] * \
                                       self.preferences_list['map_size_x'],
                                   c0.y + self.preferences_list['tilesize'] * \
                                       self.preferences_list['map_size_y'])
            
        # print "tilesize=%d, map_size_x=%d, oscale=%f" % (self.preferences_list['tilesize'],self.preferences_list['map_size_x'],self.preferences_list['oscale'])
        imgXpix = int(self.preferences_list['tilesize'] * 
                      self.preferences_list['map_size_x'] / 
                      self.preferences_list['oscale'])
        imgYpix = int(self.preferences_list['tilesize'] * 
                      self.preferences_list['map_size_y'] / 
                      self.preferences_list['oscale'])
        
        # print "Rendering Map to image of size (%d,%d) pixels" % (imgXpix,imgYpix)
        self.drawTile_bbox(bbox, imgXpix, imgYpix, fname)

        # FINISHED RENDERING THE IMAGE ===
        
        ###############################################################
        # Draw the grid on the map
        go = gridOverlay(self)
        go.render(fname)

        ##############################################################
        # Draw gpx Trace and waypoints on the map if requested
        overlay = gpxOverlay(self)
        overlay.render(fname)

        
        ###############################################################
        # Draw the point of interest markers on the map
        # (as long as the map is not too big).
        if self.preferences_list['map_size_x'] <= \
                int(self.preferences_list['maxmapsize']) and \
                self.preferences_list['map_size_y'] <= \
                int(self.preferences_list['maxmapsize']):
            addFeatures = True
        else:
            print "Map is too big to look for features: width: %s, height: %s" % (
                self.preferences_list['map_size_x'], self.preferences_list['map_size_y'])
            print "...but map size is %f x %f" % \
                (self.preferences_list['map_size_x'],
                 self.preferences_list['map_size_y'])

            addFeatures = False

        if addFeatures and not is_true(self.preferences_list['clusters']):
            print "Adding feature markers to map..."
            po = poiOverlay(self)
            po.render(fname)

        ###############################################################
        # Add clustered markers if requested.
        if is_true(self.preferences_list['clusters']):
            print "Adding Clusters to map ...."
            co = clusterOverlay(self)
            co.render(fname)

        # creating a thumbnail with the same image

        ##############################################################
        # Create a thumbnail image of the map.
        if is_true(self.preferences_list['withThumbnail']):
            thumbnail_name = "%s/thumbnail.png" % outdir
            thumb_im = Image.open(fname)
            # thumb_f = open(fname, 'w')        
            size = 256, 256
            thumb_im.thumbnail(size, Image.ANTIALIAS)
            thumb_im.save(thumbnail_name, "PNG")
예제 #25
0
파일: townguide.py 프로젝트: hixi/townguide
    def __init__(self, preferences):
        """Initialise the townguide generating class from the set of
        preferences specified in the dictionary 'preferences_list'.   The required data
        is then extracted from the database, and the selected output renderer
        called.
        """
        defaults_options = defaults.DEFAULT_PREFERENCES
        self.srs = "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs +over"

        self.preferences = preferences
        self.preferences_list = preferences.getPrefs()

        print 'PREFERENCES_LIST!!!'
        print self.preferences_list
        
        self.preferences.applyDefaults(defaults_options)
        self.preferences_list = preferences.getPrefs()
        # print "datadir=%s" % self.preferences_list['datadir']
        
        if is_true(self.preferences_list['debug']):
            self.debug = True
        else:
            self.debug = False

        # FIXME: import the fonts that are distributed with townguide.
        # if the font exists inside the data dir
        # fntPath = "%s/FreeSerif.ttf" % self.preferences_list['datadir']
        if os.path.isfile(self.preferences_list['datadir']):
            print 'Custom font exists! Using that instead'
        else:
            # Use the FreeSerif font that is bundled with townguide
            print "Could not find custom font!!!"
            print "Using the bundled font from Townguide"
            pk_path, filename =  os.path.split(os.path.abspath(__file__))
            self.fntPath = os.path.join(pk_path, 'fonts', 'DroidSans.ttf')
            print "font located at: ", self.fntPath
        
        print "fntPath = %s." % self.fntPath



        # Getting lat and long
        (lat,lon) = self.preferences_list['origin'].split(',')
        
        lat = float(lat)
        lon = float(lon)

        (map_size_x,map_size_y) = self.preferences_list['mapsize'].split(',')
        map_size_x = int(map_size_x)
        map_size_y = int(map_size_y)
        self.preferences_list['map_size_x'] = map_size_x
        self.preferences_list['map_size_y'] = map_size_y
        self.preferences_list['tilesize'] = float(self.preferences_list['tilesize'])
        oscale = float(self.preferences_list['oscale'])
        self.preferences_list['oscale'] = float(self.preferences_list['oscale'])
        
        # self.features is the list of map features to be presented.
        self.features = []
        featstrs = self.preferences_list['features'].split(',')
        for feat in featstrs:
            self.features.append(str(feat.strip()))
        # if self.debug: print self.features
        # if self.debug: print "lat=%f, lon=%f, map_size_x=%d, map_size_y=%d" % (lat,lon,map_size_x,map_size_y)

        #Convert the lat/long origin into mercator projection metres.
        prj = mapnik.Projection(self.srs)
        self.c0 = prj.forward(mapnik.Coord(lon,lat))

        print "Origin (%f,%f) is equivalent to (%f,%f) in projection" %\
              (lon,lat,self.c0.x,self.c0.y)

        self.lat = lat
        self.lon = lon
        self.map_size_x = map_size_x
        self.map_size_y = map_size_y

        self.tilesize = float(self.preferences_list['tilesize'])
        self.oscale = oscale
        self.uname = self.preferences_list['uname']
        self.dbname = self.preferences_list['dbname']

        self.title = self.preferences_list['title']
        self.outdir = self.preferences_list['outdir']

        if not os.path.exists(self.outdir):
            os.makedirs(self.outdir)

        # ====== DOWNLOAD WITH THE XAPI ==============
        downloadStr = self.preferences_list['download']
        downloadStr = downloadStr.lower()
        if is_true(downloadStr):
            self.populateDB()
        # ============================================

        print "Extracting Map Features from Database"
        self.streetIndex = {}
        self.amenities = {}
        
        # Experimental Cluster Markers
        self.clusters = []
        
        self.amenitiesSorted = {}
        maxsize = int(self.preferences_list['maxmapsize'])
        if self.preferences_list['map_size_x'] <= int(self.preferences_list['maxmapsize']) and \
        self.preferences_list['map_size_y'] <= int(self.preferences_list['maxmapsize']):
            #FIXME:  This is wrong - we need to get the data even if we do not
            # want a street index.
            #if self.preferences_list['streetIndex'].lower() == 'true':
            self.getAmenities()
        else:
            print "Map is too big ==================================="
            print "Must be less than %d km across" % int(self.preferences_list['maxmapsize'])
            print "...but map size is %f x %f" % \
                (self.preferences_list['map_size_x'],
                 self.preferences_list['map_size_y'])
        # Supported plugins
        # Plugin support: change 2
        {'book':       self.renderBook,
         'html':       self.renderHTML,
         'poster':     self.renderPoster,
         'newposter':  self.renderNewPoster,
         'simplelandscape': self.renderSimpleLandscape,
         'simpleposter': self.renderSimplePoster,
         }[self.preferences_list['format']]()    
예제 #26
0
def main(event, context):
    Stage = os.environ['STAGE']

    body = json.loads(event.get('body', {}))

    if is_true(body.get('debug', '')):
        configure_logging(level="DEBUG")

    logging.debug(f'main entry Stage:{Stage} ')
    logging.debug(f'event: {event}')
    logging.debug(f'context: {context}')
    logging.debug(f'body: {body}')
    receipt = body.get('receipt', '')

    dynamodb = boto3.resource('dynamodb')
    result_hash_table = dynamodb.Table(os.environ['RESULT_TABLE_NAME'])
    receipt_hash_table = dynamodb.Table(os.environ['RECEIPT_TABLE_NAME'])

    if os.environ['STAGE'] != 'dev':
        if body.get('verify_receipt') or body.get(
                'product_id'):  # todo: Use a whitelist rather than a blacklist
            response = {
                'isBase64Encoded':
                False,
                'statusCode':
                400,
                'headers': {},
                'body':
                json.dumps({
                    'message': 'dev-only parameter included in request!',
                    'push_txn_hash': None,
                    'config': None,
                    'seller': None,
                })
            }
            logging.debug(
                f'dev-only parameter included in request! response: {response}'
            )
            return response

    receipt_hash = hashlib.sha256(receipt.encode('utf-8')).hexdigest()

    result = result_hash_table.query(
        ConsistentRead=True,
        KeyConditionExpression=Key('receipt').eq(receipt_hash))
    if (Stage != 'dev' and result['Count'] > 0):  # we found a match, return it
        item = result['Items'][0]
        config = item['config']
        push_txn_hash = item['push_txn_hash']
        response = {
            "isBase64Encoded":
            False,
            "statusCode":
            200,
            "headers": {},
            "body":
            json.dumps({
                "push_txn_hash": push_txn_hash,
                "config": config,
                "seller": os.environ['VERIFIER'],
            })
        }
        logging.debug(
            f'found existing match for receipt_hash({receipt_hash}), result: {response}'
        )
        return response

    verify_receipt = body.get('verify_receipt', 'False')
    if (is_true(verify_receipt)):
        result = receipt_hash_table.query(
            ConsistentRead=True,
            KeyConditionExpression=Key('receipt').eq(receipt_hash))
        if (result['Count'] > 0):  # we found a match - reject on duplicate
            response = {
                "isBase64Encoded":
                False,
                "statusCode":
                402,
                "headers": {},
                "body":
                json.dumps({
                    "message": "Validation Failure: duplicate receipt!",
                    "push_txn_hash": None,
                    "config": None,
                    "seller": None,
                })
            }
            logging.debug(f'response: {response}')
            return response

    apple_response = process_app_pay_receipt(receipt)

    if (apple_response[0] or verify_receipt == 'False'):
        validation_result: dict = apple_response[1]
        if validation_result is None:
            bundle_id = ''
        else:
            bundle_id = validation_result.get('receipt',
                                              {}).get('bundle_id', '')
        if bundle_id != 'OrchidTechnologies.PAC-Test' and is_true(
                verify_receipt):  # Bad bundle_id and set to verify_receipts
            logging.debug(
                f'Incorrect bundle_id: {bundle_id} (Does not match OrchidTechnologies.PAC-Test)'
            )
            response = {
                "isBase64Encoded":
                False,
                "statusCode":
                400,
                "headers": {},
                "body":
                json.dumps({
                    'message':
                    f'Incorrect bundle_id: {bundle_id} (Does not match OrchidTechnologies.PAC-Test)',
                    'push_txn_hash': None,
                    'config': None,
                    'seller': None,
                })
            }
        else:  # Good bundle_id or not verifying receipts
            product_id = body.get(
                'product_id',
                validation_result['receipt']['in_app'][0]['product_id'])
            quantity = int(
                validation_result['receipt']['in_app'][0]['quantity'])
            if os.environ['STAGE'] == 'dev':
                total_usd = wildcard_product_to_usd(
                    product_id=product_id) * quantity
            else:
                total_usd = product_to_usd(product_id=product_id) * quantity
            logging.debug(f'product_id: {product_id}')
            logging.debug(f'quantity: {quantity}')
            logging.debug(f'total_usd: {total_usd}')
            if total_usd < 0:
                logging.debug('Unknown product_id')
                response = {
                    "isBase64Encoded":
                    False,
                    "statusCode":
                    400,
                    "headers": {},
                    "body":
                    json.dumps({
                        'message': f"Unknown product_id: {product_id}",
                        'push_txn_hash': None,
                        'config': None,
                        'seller': None,
                    })
                }
            else:
                push_txn_hash, config, signer_pubkey = get_account(
                    price=total_usd)
                if config is None:
                    response = {
                        "isBase64Encoded":
                        False,
                        "statusCode":
                        404,
                        "headers": {},
                        "body":
                        json.dumps({
                            "message": "No Account Found",
                            "push_txn_hash": None,
                            "config": None,
                            "seller": None,
                        })
                    }
                else:
                    response = {
                        "isBase64Encoded":
                        False,
                        "statusCode":
                        200,
                        "headers": {},
                        "body":
                        json.dumps({
                            "push_txn_hash": push_txn_hash,
                            "config": config,
                            "seller": os.environ['VERIFIER'],
                        })
                    }
                    item = {
                        'receipt': receipt_hash,
                    }
                    ddb_item = json.loads(
                        json.dumps(item), parse_float=Decimal
                    )  # Work around DynamoDB lack of float support
                    receipt_hash_table.put_item(Item=ddb_item)

                    item = {
                        'receipt': receipt_hash,
                        'config': config,
                        'push_txn_hash': push_txn_hash,
                        'seller': os.environ['VERIFIER'],
                    }
                    ddb_item = json.loads(
                        json.dumps(item), parse_float=Decimal
                    )  # Work around DynamoDB lack of float support
                    result_hash_table.put_item(Item=ddb_item)

                    if is_true(os.environ.get('ENABLE_MONITORING',
                                              '')):  # Jay may not like this
                        token_name = get_token_name(
                            address=os.environ['TOKEN'])
                        token_symbol = get_token_symbol(
                            address=os.environ['TOKEN'])
                        token_decimals = get_token_decimals(
                            address=os.environ['TOKEN'])
                        pac_tokens = look(funder=get_secret(
                            key=os.environ['PAC_FUNDER_PUBKEY_SECRET']),
                                          signer=signer_pubkey)
                        # lambda_metric(
                        #     f"orchid.pac.sale.{token_symbol.lower()}",
                        #     pac_tokens,
                        #     tags=[
                        #         f'token_name:{token_name}',
                        #         f'token_symbol:{token_symbol}',
                        #         f'token_decimals:{token_decimals}',
                        #         f'usd:{total_usd}',
                        #     ]
                        # )

    else:
        response = {
            "isBase64Encoded":
            False,
            "statusCode":
            402,
            "headers": {},
            "body":
            json.dumps({
                "message": f"Validation Failure: {apple_response[1]}",
                "push_txn_hash": None,
                "config": None,
                "seller": None,
            })
        }
    logging.debug(f'response: {response}')
    return response
예제 #27
0
def main(event, context):
    Stage = os.environ['STAGE']

    body = json.loads(event.get('body', {}))

    if is_true(body.get('debug', '')):
        configure_logging(level="DEBUG")

    logging.debug(f'main entry Stage:{Stage} ')
    logging.debug(f'event: {event}')
    logging.debug(f'context: {context}')
    logging.debug(f'body: {body}')
    receipt = body.get('receipt', '')

    dynamodb = boto3.resource('dynamodb')
    result_hash_table = dynamodb.Table(os.environ['RESULT_TABLE_NAME'])
    receipt_hash_table = dynamodb.Table(os.environ['RECEIPT_TABLE_NAME'])

    #check for dev params, respond with error in prod
    if os.environ['STAGE'] != 'dev':
        if body.get('verify_receipt') or body.get('product_id'):
            return response_error_invalid_dev_param()

    #extract and hash the receipt body payload
    receipt_hash = hash_receipt_body(receipt)

    #find any matching previous pot result and conditionally return it (idempotency)
    response = find_previous_pot(result_hash_table, receipt_hash,
                                 os.environ['VERIFIER'], Stage)
    if (response != None):
        return response

    #find and error return for any previous claim of the receipt (replay prevention) todo: this is not concurrent-safe, claim needs to be atomic
    verify_receipt = body.get('verify_receipt', 'True')
    if (is_true(verify_receipt)):
        response = find_previous_receipt_claim(receipt_hash_table,
                                               receipt_hash)
        if (response != None):
            return response

    apple_response = process_app_pay_receipt(receipt)

    if (apple_response[0] or verify_receipt == 'False'):
        validation_result: dict = apple_response[1]
        if validation_result is None:
            bundle_id = ''
        else:
            bundle_id = validation_result.get('receipt',
                                              {}).get('bundle_id', '')

        if bundle_id != os.environ['BUNDLE_ID'] and is_true(
                verify_receipt):  # Bad bundle_id and set to verify_receipts
            response = response_invalid_bundle(bundle_id)
        else:  # Good bundle_id or not verifying receipts
            product_id = body.get(
                'product_id',
                validation_result['receipt']['in_app'][0]['product_id'])
            quantity = int(
                validation_result['receipt']['in_app'][0]['quantity'])
            if os.environ['STAGE'] == 'dev':
                total_usd = wildcard_product_to_usd(
                    product_id=product_id) * quantity
            else:
                total_usd = product_to_usd(product_id=product_id) * quantity
            logging.debug(f'product_id: {product_id}')
            logging.debug(f'quantity: {quantity}')
            logging.debug(f'total_usd: {total_usd}')
            if total_usd <= 0:
                response = response_invalid_product(product_id)
            else:
                #find/claim a valid pot
                push_txn_hash, config, signer_pubkey = get_account(
                    price=total_usd)
                if config is None:
                    response = response_no_account()
                else:
                    response = response_valid_account(push_txn_hash, config,
                                                      os.environ['VERIFIER'])

                    #claim the receipt (conditionally atomically, exception fails if already exists)
                    if (Stage != 'dev'):
                        claim_receipt(receipt_hash_table, receipt_hash)

                    #store result (idempotency)
                    store_result(result_hash_table, receipt_hash, config,
                                 push_txn_hash, os.environ['VERIFIER'])

                    if is_true(os.environ.get('ENABLE_MONITORING',
                                              '')):  # Jay may not like this
                        do_evil_monitoring()

    else:
        response = response_invalid_receipt(apple_response)
    logging.debug(f'response: {response}')
    return response
예제 #28
0
def get_account_(
        price: float,
        blocknum: int) -> Tuple[Optional[str], Optional[str], Optional[str]]:
    logging.debug(f'get_account_ price:{price}')
    dynamodb = boto3.resource('dynamodb')
    table = dynamodb.Table(os.environ['TABLE_NAME'])
    response = random_scan(table, price)
    ret = None
    signer_pubkey = '0xTODO'
    epoch_time = int(time.time())
    for item in response['Items']:
        if float(price) == float(item['price']):
            signer_pubkey = item['signer']
            config = item['config']
            push_txn_hash = item['push_txn_hash']
            creation_etime = item.get('creation_etime', 0)
            age = epoch_time - creation_etime

            if is_true(os.environ['DOUBLE_CHECK_ACCOUNTS']):
                old_status = item['status']
                status = get_transaction_status(push_txn_hash, blocknum)
                if old_status != status:
                    logging.warning(
                        f'DynamoDB status of {old_status} for {push_txn_hash} '
                        f'does not match new status of {status}!')
            else:
                status = item['status']

            if ((status != 'confirmed')
                    and (age < 10 * 60 * 60)):  # 10 hour grace period
                logging.debug(
                    f'Skipping account ({push_txn_hash}) with status: {status} age: {age}'
                )
                continue

            logging.debug(
                f'Found potential account ({push_txn_hash}) status: {status} age:{age} config: {config}'
            )
            key = {
                'price': item['price'],
                'signer': signer_pubkey,
            }
            delete_response = table.delete_item(Key=key,
                                                ReturnValues='ALL_OLD')
            if (delete_response['Attributes'] is not None
                    and len(delete_response['Attributes']) > 0):
                balance, escrow, _ = look(
                    funder=get_secret(
                        key=os.environ['PAC_FUNDER_PUBKEY_SECRET']),
                    signer=signer_pubkey,
                )
                # update succeeded
                if ((status == 'confirmed') and (escrow > get_min_escrow())):
                    ret = push_txn_hash, config, signer_pubkey
                    break
                else:
                    logging.debug(
                        f'broken account: {push_txn_hash} status: {status}  age: {age} '
                        f'balance: {balance} deleted and skipped')
            else:
                logging.debug('Account was already deleted!')
    if ret:
        return ret
    return None, None, None