Ejemplo n.º 1
0
    def handle(self, **options):
        print(randomKey())
        companies = apiCall("torn", "", "companies", randomKey())
        # print(companies)
        for k, v in companies["companies"].items():
            positions = v["positions"]
            specials = v["specials"]
            for k1, v1 in v["stock"].items():
                v1["cost"] = 0 if v1["cost"] == "" else v1["cost"]
            stocks = v["stock"]
            del v["positions"]
            del v["specials"]
            del v["stock"]
            # print(k, v)
            # print(stock)
            # print(positions)
            # print(specials)

            company, create = CompanyDescription.objects.update_or_create(
                tId=k, defaults=v)
            print(company, create)
            for k1, v1 in positions.items():
                position, create = company.position_set.update_or_create(
                    name=k1, defaults=v1)
                print("\t", position, create)
            for k1, v1 in stocks.items():
                stocks, create = company.stock_set.update_or_create(
                    name=k1, defaults=v1)
                print("\t", stocks, create)
            for k1, v1 in specials.items():
                special, create = company.special_set.update_or_create(
                    name=k1, defaults=v1)
                print("\t", special, create)
Ejemplo n.º 2
0
    def update(self, key=None):
        if key is None:
            key = randomKey()

        # req = requests.get('https://api.torn.com/user/{}?&selections=profile,timestamp&key={}'.format(self.tId, key)).json()
        req = apiCall("user",
                      self.tId,
                      "profile,timestamp",
                      key=key,
                      verbose=False)

        if 'apiError' in req:
            return req['apiError']
        else:
            self.name = req.get("name", "?")
            self.updateTS = int(req.get("timestamp", 0))
            states = req.get("states")
            status = req.get("status")

            if states['hospital_timestamp']:
                self.hospitalTS = states['hospital_timestamp']
                self.status = 'hospitalized'
            else:
                self.status = status["details"]

            # print("[loot.NPC.update] {}: {} {} {}".format(self, self.status, self.hospitalTS, self.updateTS))
            self.save()
Ejemplo n.º 3
0
    def handle(self, **options):

        # api call
        upgrades = apiCall('torn', '', 'factiontree', key=randomKey(), sub="factiontree")
        if 'apiError' in upgrades:
            print("upgrades {}".format(upgrades))
            return False

        # get max level
        maxlevel = dict()
        for tId, upgrade in upgrades.items():
            maxlevel[tId] = 0
            for level, v in upgrade.items():
                # compute max level
                maxlevel[tId] = max(maxlevel[tId], int(level))

                # get short name
                splt = v["name"].split(" ")
                v["shortname"] = " ".join(splt[:-1]) if re.match(r"([IVX]{1,5})", splt[-1]) else v["name"]
                v["shortname"] = v["shortname"].strip()

                # update database
                print(FactionTree.objects.update_or_create(tId=tId, level=level, defaults=v))

        # update database with max level
        for tId, level in maxlevel.items():
            FactionTree.objects.filter(tId=tId).update(maxlevel=level)
Ejemplo n.º 4
0
    def handle(self, **options):
        print("[command.bazaar.scan] start")

        items = apiCall("torn",
                        "",
                        "items,timestamp",
                        randomKey(),
                        sub="items",
                        verbose=False)

        itemType = dict({})

        if items is None:
            print("[command.bazaar.scan] item is None")
        elif 'apiError' in items:
            print("[command.bazaar.scan] api error: {}".format(
                items["apiError"]))
        else:
            for k, v in items.items():
                type = v["type"]
                name = v["name"].split(":")[0].strip()
                if type in itemType:
                    if name not in itemType[type]:
                        itemType[type].append(name)
                else:
                    itemType[type] = [name]
                req = Item.objects.filter(tId=int(k))
                if len(req) == 0:
                    item = Item.create(k, v)
                    item.save()
                elif len(req) == 1:
                    item = req[0]
                    item.update(v)
                    # if item.onMarket:
                    #     key = preference.get_random_key()[1]
                    #     item.update_bazaar(key=key, n=preference.nItems)
                    item.save()
                else:
                    print(
                        "[command.bazaar.scan]: request found more than one item id",
                        len(req))
                    return 0

            bd = BazaarData.objects.first()
            bd.lastScanTS = int(timezone.now().timestamp())
            bd.save()

        # delete bazaar info for custom items refreshed more than 24h ago
        items = Item.objects.filter(onMarket=False).filter(
            lastUpdateTS__lt=(int(timezone.now().timestamp()) - 86400))
        for item in items:
            item.marketdata_set.all().delete()

        bd = BazaarData.objects.first()
        bd.itemType = json.dumps(itemType)
        bd.save()

        print("[command.bazaar.scan] end")
Ejemplo n.º 5
0
    def handle(self, **options):
        print("[command.stock.update] start")

        stocks = apiCall("torn", "", "stocks,timestamp", randomKey())
        for k, v in stocks["stocks"].items():
            stock = Stock.objects.filter(tId=int(k)).first()
            if stock is None:
                stock = Stock.create(k, v, stocks["timestamp"])
            else:
                stock.update(k, v, stocks["timestamp"])
            stock.save()

        print("[command.stock.update] end")
Ejemplo n.º 6
0
    def handle(self, **options):
        print(f"[CRON {logdate()}] START stocks")

        stocks = apiCall("torn", "", "stocks,timestamp", randomKey())
        for k, v in stocks["stocks"].items():
            stock = Stock.objects.filter(tId=int(k)).first()
            if stock is None:
                stock = Stock.create(k, v, stocks["timestamp"])
            else:
                stock.update(k, v, stocks["timestamp"])
            stock.save()

        print(f"[CRON {logdate()}] END")
Ejemplo n.º 7
0
    def handle(self, **options):
        print("[command.chain.territories] start")

        territories = apiCall("torn",
                              "",
                              "territory,rackets",
                              randomKey(),
                              verbose=False)
        #
        print("[command.chain.territories] update territories")
        allTerr = territories.get("territory", dict({}))
        allRack = territories.get("rackets", dict({}))
        n = len(allTerr)
        for i, (k, v) in enumerate(allTerr.items()):
            v["racket"] = json.dumps(allRack.get(k, dict({})))
            terr, _ = Territory.objects.update_or_create(tId=k, defaults=v)
            print("{}/{} {}".format(i + 1, n, terr))

        # delete old racket
        for r in Racket.objects.only("tId").all():
            if r.tId not in allRack:
                print("Delete {}".format(r))
                r.delete()

        n = len(allRack)
        for i, (k, v) in enumerate(allRack.items()):
            if v.get("war", False):
                v["assaulting_faction"] = v["war"]["assaulting_faction"]
                v["defending_faction"] = v["war"]["defending_faction"]
                v["started"] = v["war"]["started"]
                v["ends"] = v["war"]["ends"]
                v["war"] = True
            else:
                v["war"] = False
                v["assaulting_faction"] = 0
                v["defending_faction"] = 0
                v["started"] = 0
                v["ends"] = 0

            r, _ = Racket.objects.update_or_create(tId=k, defaults=v)
            print("{}/{} {}".format(i + 1, n, r))

        fd = FactionData.objects.first()
        fd.territoryUpda = tsnow()
        fd.save()

        print("[command.chain.territories] end")
Ejemplo n.º 8
0
    def handle(self, **options):
        print(f"[CRON {logdate()}] START territories")

        territories = apiCall("torn",
                              "",
                              "territory,rackets",
                              randomKey(),
                              verbose=False)
        #
        allTerr = territories.get("territory", dict({}))
        allRack = territories.get("rackets", dict({}))
        n = len(allTerr)
        for i, (k, v) in enumerate(allTerr.items()):
            v["racket"] = json.dumps(allRack.get(k, dict({})))
            terr, _ = Territory.objects.update_or_create(tId=k, defaults=v)
            print(f"[CRON {logdate()}] {i + 1}/{n} {terr}")

        # delete old racket
        for r in Racket.objects.only("tId").all():
            if r.tId not in allRack:
                print(f"[CRON {logdate()}] Delete {r}")
                r.delete()

        n = len(allRack)
        for i, (k, v) in enumerate(allRack.items()):
            if v.get("war", False):
                v["assaulting_faction"] = v["war"]["assaulting_faction"]
                v["defending_faction"] = v["war"]["defending_faction"]
                v["started"] = v["war"]["started"]
                v["ends"] = v["war"]["ends"]
                v["war"] = True
            else:
                v["war"] = False
                v["assaulting_faction"] = 0
                v["defending_faction"] = 0
                v["started"] = 0
                v["ends"] = 0

            r, _ = Racket.objects.update_or_create(tId=k, defaults=v)
            print(f"[CRON {logdate()}] {i + 1}/{n} {r}")

        fd = FactionData.objects.first()
        fd.territoryUpda = tsnow()
        fd.save()

        print(f"[CRON {logdate()}] END")
Ejemplo n.º 9
0
    def handle(self, **options):
        print("[command.chain.updateUpgradeTree] start")
        upgradeTree = apiCall("torn",
                              "",
                              "factiontree",
                              randomKey(),
                              sub="factiontree")
        factionData = FactionData.objects.first()
        factionData.upgradeTree = json.dumps(upgradeTree)
        factionData.save()

        # upgradeTree = json.loads(FactionData.objects.first().upgradeTree)

        # for k1, v1 in upgradeTree.items():
        #     print(k1)
        #     for k2, v2 in v1.items():
        #         print("\t", k2, v2)

        print("[command.chain.updateUpgradeTree] end")
Ejemplo n.º 10
0
    def handle(self, **options):
        print(f'[CRON {logdate()}] START stocks')
        api_stocks = apiCall("torn",
                             "",
                             "stocks,timestamp",
                             randomKey(),
                             verbose=False)

        # init bulk manager
        batch_stocks = Stock.objects.bulk_operation()
        batch_history = History.objects.bulk_operation()

        # set rounded timestamp and period
        timestamp = api_stocks["timestamp"] - api_stocks["timestamp"] % 60
        periods = {
            "h": timestamp - 3600,
            "d": timestamp - 3600 * 24,
            "w": timestamp - 3600 * 24 * 7,
            "m": timestamp - 3600 * 24 * 7 * 31
        }

        # get all stocks and history
        stocks = Stock.objects.all()
        for api_stock_id, api_stock in api_stocks.get("stocks").items():
            acronym = api_stock["acronym"]

            # init defaults
            defaults = {
                "name": api_stock["name"],
                "current_price": api_stock["current_price"],
                "requirement": api_stock["benefit"]["requirement"],
                "description": api_stock["benefit"]["description"],
                "timestamp": timestamp
            }

            batch_stocks.update_or_create(acronym=acronym, defaults=defaults)

        if batch_stocks.count():
            batch_stocks.run()

        print(f'[CRON {logdate()}] END')
Ejemplo n.º 11
0
    def handle(self, **options):
        print("[command.chain.territories] start")

        territories = apiCall("torn",
                              "",
                              "territory,rackets",
                              randomKey(),
                              verbose=False)

        print("[command.chain.territories] update territories")
        allTerr = territories.get("territory", dict({}))
        allRack = territories.get("rackets", dict({}))
        n = len(allTerr)
        for i, (k, v) in enumerate(allTerr.items()):
            terr = Territory.objects.filter(tId=k).first()
            if terr is None:
                print(f"{i+1} / {n}: create territory {k}")
                terr = Territory.objects.create(tId=k, **v)
            else:
                print(f"{i+1} / {n}: update territory {k}")
                terr.faction = v.get("faction", 0)

            racket = allRack.get(k)
            if racket is None:
                terr.racket = json.dumps(dict({}))
            else:
                terr.racket = json.dumps(racket)

            terr.save()

        Racket.objects.all().delete()
        n = len(allRack)
        for i, (k, v) in enumerate(allRack.items()):
            print(f"{i+1} / {n}: create racket {k}")
            terr = Racket.objects.create(tId=k, **v)

        fd = FactionData.objects.first()
        fd.territoryTS = int(timezone.now().timestamp())
        fd.save()

        print("[command.chain.territories] end")
Ejemplo n.º 12
0
    def update(self, key=None):
        if key is None:
            key = randomKey()

        # req = requests.get('https://api.torn.com/user/{}?&selections=profile,timestamp&key={}'.format(self.tId, key)).json()
        req = apiCall("user",
                      self.tId,
                      "profile,timestamp",
                      key=key,
                      verbose=False)

        if 'apiError' in req:
            return req['apiError']
        else:
            old_hospitalTS = self.hospitalTS
            self.name = req.get("name", "?")
            self.updateTS = int(req.get("timestamp", 0))
            states = req.get("states")
            status = req.get("status")

            if states['hospital_timestamp']:
                self.hospitalTS = states['hospital_timestamp']
                self.status = 'hospitalized'
            else:
                self.status = status["details"]

            # print("[loot.NPC.update] {}: {} {} {}".format(self, self.status, self.hospitalTS, self.updateTS))
            self.save()

        # clear context processor caching caching
        # clear cloudfare caching
        if old_hospitalTS != self.hospitalTS:
            print("[loot.NPC.update] clear cache")
            cache.delete("context_processor_loot")
            # cache.delete("api_loot")
            r = clear_cf_cache([
                "https://yata.yt/api/v1/loot/", "https://yata.yt/api/v1/loot"
            ])
Ejemplo n.º 13
0
    def updateApiCall(self):
        req = apiCall("torn", "", "medals,honors", randomKey())

        if 'apiError' in req:
            print(req["apiError"])
        else:
            self.timestamp = int(timezone.now().timestamp())
            popTotal = 0
            for awardType in ["honors", "medals"]:
                to_del = []
                for k, v in req[awardType].items():
                    circulation = int(req[awardType][k].get("circulation", 0))
                    if v.get("type") in [1]:
                        to_del.append(k)
                    else:
                        if circulation > 1:
                            popTotal += 1. / computeRarity(circulation)
                    if awardType in ["honors"]:
                        req[awardType][k][
                            "img"] = "https://awardimages.torn.com/{}.png".format(
                                d.get(int(k), 0))
                        req[awardType][k]["unreach"] = 1 if int(
                            k) in HONORS_UNREACH else 0
                    elif awardType in ["medals"]:
                        req[awardType][k]["img"] = "{}".format(k)
                for k in to_del:
                    del req[awardType][k]

            for awardType in ["honors", "medals"]:
                for k, v in req[awardType].items():
                    if v["circulation"] > 1:
                        req[awardType][k]["rScore"] = 100. / computeRarity(
                            v["circulation"]) / popTotal

            self.apicall = json.dumps(req)
            self.save()
Ejemplo n.º 14
0
    def handle(self, **options):
        print("[command.chain.updateUpgradeTree] start")
        upgradeTree = apiCall("torn",
                              "",
                              "factiontree",
                              randomKey(),
                              sub="factiontree")
        for k1, v1 in upgradeTree.items():
            for k2, v2 in v1.items():
                ch = v2["challenge"].replace(",", "").replace("$", "")

                # no challenge
                if ch in ["No challenge"]:
                    upgradeTree[k1][k2]["challengeprogress"] = [None, None]

                # Escape
                elif re.match(r'Run away \b(\d{1,4})\b times', ch):
                    key = "attacksrunaway"
                    val = int(ch.split(" ")[2])
                    upgradeTree[k1][k2]["challengeprogress"] = [key, val]

                # Maximum Life
                elif re.match(
                        r'Win \b(\d{1,6})\b damage receiving attacks or defends',
                        ch):
                    key = "attacksdamaging"
                    val = int(ch.split(" ")[1])
                    upgradeTree[k1][k2]["challengeprogress"] = [key, val]

                # Accuracy
                elif re.match(r'Achieve \b(\d{1,6})\b damaging hits', ch):
                    key = "attacksdamagehits"
                    val = int(ch.split(" ")[1])
                    upgradeTree[k1][k2]["challengeprogress"] = [key, val]

                # Damage
                elif re.match(r'Deal \b(\d{1,10})\b damage', ch):
                    key = "attacksdamage"
                    val = int(ch.split(" ")[1])
                    upgradeTree[k1][k2]["challengeprogress"] = [key, val]

                # Hospitalization
                elif re.match(
                        r'Put opponents in hospital for \b(\d{1,10})\b hours',
                        ch):
                    key = "hosptimegiven"
                    val = int(ch.split(" ")[5])
                    upgradeTree[k1][k2]["challengeprogress"] = [key, val]

                # Training
                elif re.match(
                        r'Spend \b(\d{1,9})\b energy on (\w{5,}) training',
                        ch):
                    key = "gym" + ch.split(" ")[4]
                    val = int(ch.split(" ")[1])
                    upgradeTree[k1][k2]["challengeprogress"] = [key, val]

                # Rehab cost
                elif re.match(r'Rehab \b(\d{1,9})\b times', ch):
                    key = "rehabs"
                    val = int(ch.split(" ")[1])
                    upgradeTree[k1][k2]["challengeprogress"] = [key, val]

                # Travel cost
                elif re.match(r'Achieve \b(\d{1,9})\b hours of flight', ch):
                    key = "traveltime"
                    val = int(ch.split(" ")[1])
                    upgradeTree[k1][k2]["challengeprogress"] = [key, val]

                # Oversea banking
                elif re.match(r'Receive \b(\d{1,9})\b in Cayman interest', ch):
                    key = "caymaninterest"
                    val = int(ch.split(" ")[1])
                    upgradeTree[k1][k2]["challengeprogress"] = [key, val]

                # Hunting
                elif re.match(r'Hunt \b(\d{1,9})\b times', ch):
                    key = "hunting"
                    val = int(ch.split(" ")[1])
                    upgradeTree[k1][k2]["challengeprogress"] = [key, val]

                # Overdosing
                elif re.match(r'Overdose \b(\d{1,9})\b times', ch):
                    key = "drugoverdoses"
                    val = int(ch.split(" ")[1])
                    upgradeTree[k1][k2]["challengeprogress"] = [key, val]

                # Side Effect
                elif re.match(r'Take \b(\d{1,9})\b drugs', ch):
                    key = "drugsused"
                    val = int(ch.split(" ")[1])
                    upgradeTree[k1][k2]["challengeprogress"] = [key, val]

                # Alcohol effect
                elif re.match(r'Use \b(\d{1,9})\b bottles of alcohol', ch):
                    key = "alcoholused"
                    val = int(ch.split(" ")[1])
                    upgradeTree[k1][k2]["challengeprogress"] = [key, val]

                # Energy drink effect
                elif re.match(r'Use \b(\d{1,9})\b cans of energy drink', ch):
                    key = "energydrinkused"
                    val = int(ch.split(" ")[1])
                    upgradeTree[k1][k2]["challengeprogress"] = [key, val]

                # Candy effect
                elif re.match(r'Use \b(\d{1,9})\b bags of candy', ch):
                    key = "candyused"
                    val = int(ch.split(" ")[1])
                    upgradeTree[k1][k2]["challengeprogress"] = [key, val]

                # Medical effectiveness
                elif re.match(r'Receive \b(\d{1,9})\b hours of hospital time',
                              ch):
                    key = "hosptimereceived"
                    val = int(ch.split(" ")[1])
                    upgradeTree[k1][k2]["challengeprogress"] = [key, val]

                # Life regeneration
                elif re.match(
                        r'Recover \b(\d{1,9})\b life using medical items', ch):
                    key = "medicalitemrecovery"
                    val = int(ch.split(" ")[1])
                    upgradeTree[k1][k2]["challengeprogress"] = [key, val]

                # Reviving
                elif re.match(r'Revive \b(\d{1,9})\b people', ch):
                    key = "revives"
                    val = int(ch.split(" ")[1])
                    upgradeTree[k1][k2]["challengeprogress"] = [key, val]

                # Medical cooldown
                elif re.match(
                        r'Utilize \b(\d{1,9})\b hours of medical cooldown',
                        ch):
                    key = "medicalcooldownused"
                    val = int(ch.split(" ")[1])
                    upgradeTree[k1][k2]["challengeprogress"] = [key, val]

                # Bust skill/nerve
                elif re.match(r'Bust \b(\d{1,9})\b people from jail', ch):
                    key = "busts"
                    val = int(ch.split(" ")[1])
                    upgradeTree[k1][k2]["challengeprogress"] = [key, val]

                # Jail time
                elif re.match(r'Receive \b(\d{1,9})\b(\s{1,2})jail sentences',
                              ch):
                    key = "jails"
                    val = int(ch.split(" ")[1])
                    upgradeTree[k1][k2]["challengeprogress"] = [key, val]

                # Nerve
                elif re.match(r'Commit \b(\d{1,9})\b offences', ch):
                    key = "criminaloffences"
                    val = int(ch.split(" ")[1])
                    upgradeTree[k1][k2]["challengeprogress"] = [key, val]

                # Territory
                elif re.match(r'Hold \b([a-z\-]{1,})\b territor', ch):
                    key = "highestterritories"
                    val = int(v2["ability"].split(" ")[4]) - 1
                    upgradeTree[k1][k2]["challengeprogress"] = [key, val]

                # Capacity
                elif re.match(r'Achieve a faction age of \b(\d{1,9})\b days',
                              ch):
                    key = "age"
                    val = int(ch.split(" ")[5])
                    upgradeTree[k1][k2]["challengeprogress"] = [key, val]

                # Chaining
                elif re.match(r'Achieve a chain of \b(\d{1,9})', ch):
                    key = "best_chain"
                    val = int(ch.split(" ")[4])
                    upgradeTree[k1][k2]["challengeprogress"] = [key, val]

                # Laboratory
                elif re.match(r'Acquire \b(\d{1,9}) faction members', ch):
                    key = "members"
                    val = int(ch.split(" ")[1])
                    upgradeTree[k1][k2]["challengeprogress"] = [key, val]

                else:
                    print(k2, v2)

        # for k1, v1 in upgradeTree.items():
        #     print(k1)
        #     for k2, v2 in v1.items():
        #         print(k2, v2)

        factionData = FactionData.objects.first()
        factionData.upgradeTree = json.dumps(upgradeTree)
        factionData.save()

        # upgradeTree = json.loads(FactionData.objects.first().upgradeTree)

        # for k1, v1 in upgradeTree.items():
        #     print(k1)
        #     for k2, v2 in v1.items():
        #         print("\t", k2, v2)

        print("[command.chain.updateUpgradeTree] end")
Ejemplo n.º 15
0
    def handle(self, **options):
        print(f'[CRON {logdate()}] START stocks')
        api_stocks = apiCall("torn",
                             "",
                             "stocks,timestamp",
                             randomKey(),
                             verbose=False)

        # init bulk manager
        batch_stocks = Stock.objects.bulk_operation()
        batch_history = History.objects.bulk_operation()

        # set rounded timestamp and period
        timestamp = api_stocks["timestamp"] - api_stocks["timestamp"] % 60
        periods = {
            "h": timestamp - 3600,
            "d": timestamp - 3600 * 24,
            "w": timestamp - 3600 * 24 * 7,
            "m": timestamp - 3600 * 24 * 7 * 31
        }

        # get all stocks and history
        stocks = Stock.objects.all()
        history = History.objects.filter(timestamp__gt=periods["w"])
        for stock_id, api_stock in api_stocks.get("stocks").items():
            acronym = api_stock["acronym"]
            stock = stocks.filter(acronym=acronym).first()

            # init defaults
            defaults = {
                "torn_id": stock_id,
                "name": api_stock["name"],
                "current_price": api_stock["current_price"],
                "market_cap": api_stock["market_cap"],
                "total_shares": api_stock["total_shares"],
                "requirement": api_stock["benefit"]["requirement"],
                "description": api_stock["benefit"]["description"],
                "timestamp": timestamp
            }

            # compute live tendancy and previous price
            previous = history.filter(stock__acronym=acronym,
                                      timestamp=timestamp - 60).first()
            previous_price = stock.current_price if previous is None else previous.current_price
            defaults["previous_price"] = previous_price
            defaults["tendancy_l_a"] = (api_stock["current_price"] -
                                        previous_price) / 60

            for k, p in periods.items():
                try:
                    # compute tendencies
                    a, b = lin_reg(
                        history.filter(stock__acronym=acronym,
                                       timestamp__gt=p))
                    defaults[f'tendancy_{k}_a'] = 0 if numpy.isnan(a) else a
                    defaults[f'tendancy_{k}_b'] = 0 if numpy.isnan(b) else b

                except BaseException as e:
                    print(f'[CRON {logdate()}] Error in linear reg: {e}')
                    pass

            batch_stocks.update_or_create(acronym=acronym, defaults=defaults)

            # record history
            defaults = {
                "current_price": api_stock["current_price"],
                "market_cap": api_stock["market_cap"],
                "total_shares": api_stock["total_shares"],
            }
            batch_history.update_or_create(stock_id=stock.pk,
                                           timestamp=timestamp,
                                           defaults=defaults)

        if batch_stocks.count():
            batch_stocks.run()
        if batch_history.count():
            batch_history.run()

        print(f'[CRON {logdate()}] END')
Ejemplo n.º 16
0
    def handle(self, **options):
        print(f"[CRON {logdate()}] START items")

        points = apiCall("market",
                         "",
                         "pointsmarket",
                         randomKey(),
                         sub="pointsmarket",
                         verbose=False)
        items = apiCall("torn",
                        "",
                        "items,timestamp",
                        randomKey(),
                        sub="items",
                        verbose=False)

        itemType = dict({})

        if items is None:
            print(f"[CRON {logdate()}] item is None")
        elif 'apiError' in items:
            print(f"[CRON {logdate()}] api error: {items['apiError']}")
        else:

            bd = BazaarData.objects.first()

            total_price = 0
            total_points = 0
            for k, v in points.items():
                total_price += v["total_cost"]
                total_points += v["quantity"]
            bd.pointsValue = total_price // float(total_points)
            bd.save()

            for k, v in items.items():
                print(f'[CRON {logdate()}] Update {k} {v["name"]}')
                type = v["type"]
                name = v["name"].split(":")[0].strip()
                if type in itemType:
                    if name not in itemType[type]:
                        itemType[type].append(name)
                else:
                    itemType[type] = [name]
                req = Item.objects.filter(tId=int(k))
                if len(req) == 0:
                    item = Item.create(k, v)
                    item.save()
                elif len(req) == 1:
                    item = req[0]
                    item.update(v)
                    # if item.onMarket:
                    #     key = preference.get_random_key()[1]
                    #     item.update_bazaar(key=key, n=preference.nItems)
                    item.save()
                else:
                    print(
                        f"[CRON {logdate()}]: request found more than one item id {len(req)}"
                    )
                    return 0

            bd.lastScanTS = int(timezone.now().timestamp())
            bd.save()

        # delete bazaar info for custom items refreshed more than 24h ago
        items = Item.objects.filter(onMarket=False).filter(
            lastUpdateTS__lt=(int(timezone.now().timestamp()) - 86400))
        for item in items:
            item.marketdata_set.all().delete()

        bd = BazaarData.objects.first()
        bd.itemType = json.dumps(itemType)
        bd.save()

        print(f"[CRON {logdate()}] END")