示例#1
0
 def showstaticmatrixfortime(self, matrix, t):
     global interrupt
     timeout = timetime() + t
     while not interrupt:
         self.showstaticmatrix(matrix)
         if timetime() > timeout:
             break
示例#2
0
    def updatestaticmatrix(self, textinput, colour, hold_sec):
        global interrupt
        matrix = [[0 for i in xrange(80)] for i in xrange(8)]
        # save the ascii values of the input characters into the inputarray 
        # the font module uses the ascii value to index the font array
        inputarray = []
        for char in textinput:
            inputarray.append(ord(char))

        # dotarray is  8 X n
        # n is determined by the number of characters multiplyed by 8 
        # n will be len(dotarray[0]) after filling dotarray from characters
        # in the inputarray
        #
        dotarray = [[] for i in xrange(8)]
        #
        # fill the dot array with the colour digits
        # this is the dot pattern that we want to show
        #
        for row in range(8):
            for ascii in inputarray:
                # get the width of the character from the first element of the font variable
                width = fontv.array[ascii][0]
                binary = '{0:{fill}{align}{width}{base}}'.format(fontv.array[ascii][row + 1], base='b', fill='0',
                                                                 align='>', width=width)
                for digit in range(width):
                    if binary[digit] == '0':
                        dotarray[row].append(0)
                    else:
                        dotarray[row].append(colour)

        totalwidth = len(dotarray[0])
        if totalwidth > self.displaywidth:
            logging.warn('Message is Larger than the Display')
            return

        offset = int((self.displaywidth - totalwidth) / 2)

        # Fill the matrix initially with offset spaces to centre align the message
        #
        for col in range(offset):
            for row in range(8):
                matrix[row][col] = 0
        # now fill the rest of the matrix with the dotarray
        for col in range(totalwidth):
            for row in range(8):
                # copy the current dotarray column values to the first column in the matrix
                matrix[row][offset + col] = (dotarray[row][col])

        timeout = timetime() + hold_sec
        while not interrupt:
            self.showstaticmatrix(matrix)
            if timetime() > timeout:
                break
        return matrix
示例#3
0
    def updatescrollmatrix(self, textinput, colour, move_sec, hold_sec):
        global interrupt
        matrix = [[0 for i in xrange(80)] for i in xrange(8)]
        dotarray = [[] for i in xrange(8)]

        # append extra characters to text input to allow for wrap-around
        # textinput+='  ::  '

        # save the ascii values of the input characters into the inputarray 
        # the font module uses the ascii value to index the font array
        inputarray = []
        for char in textinput:
            inputarray.append(ord(char))
        #
        # fill the dot array with the colour digits
        # this is the dot pattern that we want to show
        #
        for row in range(8):
            for ascii in inputarray:
                # get the width of the character from the first element of the font variable
                try:
                    fontv.array[ascii]
                except IndexError:
                    ascii = 0
                width = fontv.array[ascii][0]
                # get the binary representation of the charatcter at that row
                binary = '{0:{fill}{align}{width}{base}}'.format(fontv.array[ascii][row + 1], base='b', fill='0',
                                                                 align='>', width=width)
                # Go through each bit in binary and add it to the row as either off for 0 or color for 1
                for digit in range(width):
                    if binary[digit] == '0':
                        dotarray[row].append(0)
                    else:
                        dotarray[row].append(colour)

        # loop around each column in the dotarray
        for col in range(len(dotarray[0])):
            for row in range(8):
                # copy the current dotarray column values to the first column in the matrix
                matrix[row][0] = (dotarray[row][col])
            # now that we have updated the matrix lets show it
            timeout = timetime() + move_sec
            while not interrupt:
                self.showscrollmatrix(matrix)
                if timetime() > timeout:
                    break
            # shift the matrix left ready for the next column
            self.shiftmatrix(matrix)

        timeout = timetime() + hold_sec
        while not interrupt:
            self.showscrollmatrix(matrix)
            if timetime() > timeout:
                break
示例#4
0
	def check_rate_limit(self, resource, api):
		'''
			Checks that it's OK to rip this album
			Raises exception if rip has to wait
		'''
		url = 'https://api.twitter.com/1.1/application/rate_limit_status.json?resources=%s' % quote(resource, '')
		headers = {
				'Authorization' : 'Bearer %s' % self.access_token,
				'Content-Type'  : 'application/x-www-form-urlencoded;charset=UTF-8',
				'User-agent'    : 'derv\'s ripe and zipe'
			}
		r = self.httpy.get_extended(url, headers=headers)
		json = loads(r)
		stats = json['resources'][resource][api]
		remaining = stats['remaining']
		if remaining < 20: # Within 20 of hitting rate limit, stop now
			# Not enough requests remaining to rip!
			now = int(timetime())
			diff = stats['reset'] - now # Seconds until reset
			dtime = ''
			if diff > 3600:
				dtime = '%d hours ' % (diff / 3600)
				diff %= 3600
			if diff > 60:
				dtime += '%d min ' % (diff / 60)
				diff %= 60
			if dtime == '' or diff != 0:
				dtime += '%d sec' % diff
			raise Exception('twitter is rate-limited, try again in %s' % dtime)
    def test_should_reload_when_plugin_has_been_changed(self, mock_sleep):
        self.monitor._generate_plugin_state.return_value = {'AA': 12}

        self.monitor._check_workers()

        self.monitor._spawn_new_workers.assert_not_called()  # pylint: disable=no-member
        self.monitor._kill_old_workers.assert_not_called()  # pylint: disable=no-member
        self.monitor._reload_gunicorn.assert_not_called()  # pylint: disable=no-member

        self.monitor._generate_plugin_state.return_value = {'AA': 32}

        self.monitor._check_workers()

        self.monitor._spawn_new_workers.assert_not_called()  # pylint: disable=no-member
        self.monitor._kill_old_workers.assert_not_called()  # pylint: disable=no-member
        self.monitor._reload_gunicorn.assert_not_called()  # pylint: disable=no-member

        self.monitor._generate_plugin_state.return_value = {'AA': 32}

        self.monitor._check_workers()

        self.monitor._spawn_new_workers.assert_not_called()  # pylint: disable=no-member
        self.monitor._kill_old_workers.assert_not_called()  # pylint: disable=no-member
        self.monitor._reload_gunicorn.assert_called_once_with()  # pylint: disable=no-member
        self.assertAlmostEqual(self.monitor._last_refresh_time,
                               timetime(),
                               delta=5)
示例#6
0
    def check_rate_limit(self, resource, api):
        '''
			Checks that it's OK to rip this album
			Raises exception if rip has to wait
		'''
        url = 'https://api.twitter.com/1.1/application/rate_limit_status.json?resources=%s' % quote(
            resource, '')
        headers = {
            'Authorization': 'Bearer %s' % self.access_token,
            'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
            'User-agent': 'derv\'s ripe and zipe'
        }
        r = self.httpy.get_extended(url, headers=headers)
        json = loads(r)
        stats = json['resources'][resource][api]
        remaining = stats['remaining']
        if remaining < 20:  # Within 20 of hitting rate limit, stop now
            # Not enough requests remaining to rip!
            now = int(timetime())
            diff = stats['reset'] - now  # Seconds until reset
            dtime = ''
            if diff > 3600:
                dtime = '%d hours ' % (diff / 3600)
                diff %= 3600
            if diff > 60:
                dtime += '%d min ' % (diff / 60)
                diff %= 60
            if dtime == '' or diff != 0:
                dtime += '%d sec' % diff
            raise Exception('twitter is rate-limited, try again in %s' % dtime)
 def test_should_start_new_workers_when_refresh_interval_has_passed(
         self, mock_sleep):
     self.monitor._last_refresh_time -= 200
     self.monitor._check_workers()
     self.monitor._spawn_new_workers.assert_called_once_with(2)  # pylint: disable=no-member
     self.monitor._kill_old_workers.assert_not_called()  # pylint: disable=no-member
     self.monitor._reload_gunicorn.assert_not_called()  # pylint: disable=no-member
     self.assertAlmostEqual(self.monitor._last_refresh_time,
                            timetime(),
                            delta=5)
示例#8
0
    def decrement_frame(self, _time=None, _internal_call=False):
        self.frame -= 1
        if self.frame == -1:
            self.frame = self.number_of_frames - 1

        if _time is None:
            self.last_update_time = timetime()
        else:
            self.last_update_time = _time

        for obj in self.frame_bound_objects:
            obj.decrement_frame(_time=_time, _internal_call=_internal_call)
        self._update_layer()
        return self
示例#9
0
    def set_frame(self, frame, _time=None, _internal_call=False):

        if not (0 <= frame < self.number_of_frames):
            raise GraphicsError(
                "\n\nGraphicsError: Frame to set the Animated Image to must be between (inclusive) 0 & "
                f"{self.number_of_frames - 1}, not {frame}")

        self.frame = frame

        if _time is None:
            self.last_update_time = timetime()
        else:
            self.last_update_time = _time
        self._update_layer()
        return self
示例#10
0
    def increment_frame(self, _time=None, _internal_call=False):
        self.frame += 1
        if self.frame == self.number_of_frames:
            self.frame = 0

        if _time is None:
            self.last_update_time = timetime()
        else:
            self.last_update_time = _time

        for obj in self.frame_bound_objects:
            if obj.drawn:
                obj.increment_frame(_time=_time, _internal_call=_internal_call)

        if self.callbacks["frame increment"] is not None:
            self.callbacks["frame increment"]()

        self._update_layer()
        return self
示例#11
0
    def __init__(self,
                 p,
                 frames,
                 align="center",
                 cursor="arrow",
                 update_time=1 / 30,
                 layer=0,
                 tag=None,
                 autoflush=True,
                 frame_callback=None,
                 bounds=None):

        if not (callable(frame_callback) or frame_callback is None):
            raise GraphicsError(
                "\n\nGraphicsError: Frame Increment callback for Animated Image must be a function, "
                f"not {frame_callback}")

        self.anchor = p.copy()

        self.frame = 0
        self.number_of_frames = len(frames)
        self.drawn_frame = 0
        self.frame_bound_objects = {*()}

        self.imgs = [
            Image(p, path, align=align, cursor=cursor, bounds=bounds)
            for path in frames
        ]

        self.last_update_time = timetime()
        self.update_time = update_time
        self.autoflush = autoflush

        self.moved = False

        GraphicsObject.__init__(self, [], cursor=cursor, layer=layer, tag=tag)

        self.callbacks["frame increment"] = frame_callback
示例#12
0
 def wait():
     now = float(timetime())
     if now - Reddit.last_request < 2:
         sleep(2 - (now - Reddit.last_request))
     Reddit.last_request = float(timetime())
示例#13
0
def keepMPVSynchronize(server, Id, Mateid, filepath, HEARTTIME):

    server = server + '/Port/%d' % Id
    clientname = 'client1' if Mateid == 1 else 'client2'
    postdata = {'from': clientname, 'type': 'cli-start', 'text': ''}

    print('loadfile %s ' % ('"' + filepath + '"'))

    # 打开mpv进程

    mp.slave_command('loadfile %s ' % ('"' + filepath + '"'))
    mp.slave_command('set window-scale 0.8')
    mp.slave_command('set pause yes')
    mp.slave_command('seek 0 absolute')

    try:
        while True:
            timesleep(0.5)
            #告诉服务器 该client ready
            print("Waitting for Your Mate!")
            rtext = post(server, data=postdata).text.strip()
            #待服务器ready后,返回
            if rtext != 'None':
                print("Your Mate is OnLine, Movie Start!")
                if rtext.split(':')[0] == 'ser-start':
                    # print(rtext)
                    deleta = timetime() - float(rtext.split(':')[1])

                    mp.slave_command('seek %s absolute' % deleta)
                    mp.slave_command('set pause no')
                    break

        pauseFlag = False
        while True:
            #一直控制,保持和服务器同步
            timesleep(HEARTTIME)
            nowtime = timetime()  #本地绝对时间
            playtime = float(
                mp.get_property('playback-time')) if mp.get_property(
                    'playback-time') else 0  #电影播放时间

            #该client为正常播放状态
            if not pauseFlag:
                #播放器暂停时,向服务器发送暂停指令
                if mp.get_property('pause') == 'yes':
                    pauseFlag = True
                    postdata['type'] = 'pauseOn'
                    postdata['text'] = str(playtime)
                    post(server, data=postdata).text.strip()
                    continue
                #正常情况下,发送该client播放时间,等待服务器指令
                else:
                    postdata['type'] = 'normal'
                    postdata['text'] = '%s:%s' % (str(nowtime), str(playtime))
                    rtext = post(server, data=postdata).text.strip()

                    #如果服务器没有指令,继续循环
                    if rtext == 'None':
                        continue

                    #被动客户端
                    #pause表示服务器已经暂停,本地需要暂停
                    elif 'pause:On' in rtext:
                        mp.slave_command('set pause yes')
                        server_time, server_playtime = map(
                            lambda x: float(x),
                            rtext.split(':')[-2:])
                        mp.slave_command(
                            'seek %s absolute' %
                            str(nowtime - server_time + server_playtime))
                        pauseFlag = True
                        continue
                    #服务器有指令时
                    #seek为本地播放时间和服务器不同步时,主动同步到服务器播放时间
                    #"seek:2.2" 指令:差距时间
                    elif 'seek' in rtext:
                        delta = float(rtext.split(':')[1])
                        nowplaytime = float(mp.get_property('playback-time'))
                        server_playtime = nowplaytime + delta
                        mp.slave_command('seek %s absolute' %
                                         str(server_playtime))
                        continue

            #当该client暂停的时候,现在只需要监测该client和服务器是否结束暂停
            #pauseFlag==True
            else:
                #该client已经不再暂停,让服务器解除暂停
                if mp.get_property('pause') == 'no':
                    pauseFlag = False
                    postdata['type'] = 'pauseOff'
                    postdata['text'] = '%s:%s' % (str(nowtime), str(playtime))
                    rtext = post(server, data=postdata).text.strip()

                    # print(rtext)
                    #防止被动客户端主动取消暂停
                    if 'pauseAndSeek' in rtext:
                        server_playtime = float(rtext.split(':')[1])
                        pauseFlag = True
                        mp.slave_command('set pause yes')
                        mp.slave_command('seek %s absolute' %
                                         str(server_playtime))

                #该client仍然处于暂停阶段
                #为被动客户端结束暂停
                # mp.get_property('pause')=='yes'
                else:
                    postdata['type'] = 'pauseStatus'
                    postdata['text'] = ''
                    ...  #待修改
                    rtext = post(server, data=postdata).text.strip()
                    #服务器已经不再暂停,被动客户端也不暂停
                    if 'pause:Off' in rtext:
                        server_time, server_playtime = map(
                            lambda x: float(x),
                            rtext.split(':')[-2:])
                        mp.slave_command('set pause no')
                        mp.slave_command(
                            'seek %s absolute' %
                            str(nowtime - server_time + server_playtime))
                        pauseFlag = False
                    continue

    finally:
        mp.process.kill()
示例#14
0
文件: Reddit.py 项目: gwely/Redownr
	def wait():
		now = float(timetime())
		if now - Reddit.last_request < 2:
			sleep(2 - (now - Reddit.last_request))
		Reddit.last_request = float(timetime())
示例#15
0
 def default(self, obj):
     if isinstance(obj, datetime.datetime) | \
             isinstance(obj, datetime.date) | \
             isinstance(obj, datetime.time):
         return int(timetime())
     return JSONEncoder.default(self, obj)
示例#16
0
 def default(self, obj):
     if isinstance(obj, datetime.datetime) | \
         isinstance(obj, datetime.date) | \
         isinstance(obj, datetime.time):
         return int(timetime())
     return JSONEncoder.default(self, obj)
示例#17
0
def current_timestamp():
    return int(timetime())
def get_time_string_east8():
    last_time = strftime("%Y-%m-%d %H:%M:%S", localtime(timetime()))
    last_time = datetime.datetime.strptime(last_time, "%Y-%m-%d %H:%M:%S")
    last_time = last_time.astimezone(
        datetime.timezone(datetime.timedelta(hours=8)))
    return last_time
示例#19
0
async def loadimages():
    global kb
    global DEBUGCHANNEL
    global botup
    global errortype
    botup = True
    errortype = None
    k = None
    try:
        for kills in await kb.newkills():
            k = kill(kills, DEBUGCHANNEL)
            await k.draw()
            print(k.eventid, end=" ")
            # loop through guilds
            embedder, fileobj = None, None
            for guilds in [c for c in configs if c != "GENERAL"]:
                if configs[guilds]["sendchannel"] == 0:
                    continue
                if kb.qualify(configs[guilds], dc(kills)):
                    embedder, fileobj = k.create_embed(
                        configs[guilds]["trackingplayer"] +
                        configs[guilds]["trackingguild"])
                    while not isfile(k.fileloc):
                        await k.draw()
                    # load send channel
                    channel = discord.utils.find(
                        lambda x: x.id == int(configs[guilds]["sendchannel"]),
                        bot.get_all_channels())
                    if not channel:
                        continue
                    await channel.trigger_typing()
                    count = 0
                    while True:
                        try:
                            await channel.send(file=fileobj, embed=embedder)
                            break
                        except discord.errors.HTTPException:
                            continue
                        except Exception as e:
                            raise
            # Deletes file
            try:
                # file still exists, channel si not set if fileloc is None
                os.remove(k.fileloc)
            except Exception as e:
                await DEBUGCHANNEL.send(
                    f"{DEBUGCHANNEL.guild.owner.mention} {e.__class__.__name__} in kill {k.eventid}\nCaused by `{k.args[0]}`"
                )
                botup = False
                continue
            print(round(timetime() - k.starttime, 3))
            del k
        generalconfigs()
        print("Finished")
        return
    except Exception as e:
        botup = False
        errortype = str(e.__class__.__name__)
        logging.warning(f"{e.__class__.__name__}", exc_info=True)
        try:
            await DEBUGCHANNEL.send(
                f"{DEBUGCHANNEL.guild.owner.mention} {e.__class__.__name__} in kill {k.eventid}\nCaused by `{e.args[0]}`"
            )
        except:
            await DEBUGCHANNEL.send(
                f"{DEBUGCHANNEL.guild.owner.mention} {e.__class__.__name__} is caused by unknnown error"
            )
示例#20
0
ALIGN_OPTIONS = {
    "top", "left", "right", "bottom", "center", "topleft", "topright",
    "bottomleft", "bottomright"
}

INTERPOLATIONS = {
    "linear", "poly", "poly_in", "poly_out", "sin", "sin_in", "sin_out",
    "circle", "circle_in", "circle_out", "back", "back_in", "back_out",
    "bounce", "bounce_in", "bounce_out", "elastic", "elastic_in",
    "elastic_out", "exponential", "exponential_in", "exponential_out"
}

ALL_CHARACTERS = {
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e',
    'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
    'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
    'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
    'Y', 'Z', '!', '"', '#', '$', '%', '&', '\\', "'", '(', ')', '*', '+', ',',
    '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '{', '\'', '"', '}', '^',
    '_', '`', '{', '|', '}', '~', ':', " "
}

##########################################################################
# global variables and functions

_root = tkTk()
_root.withdraw()

_update_lasttime = timetime()
示例#21
0
 def __init__(self, kd, debugchannel=None):
     """
     Usage: 
     variable = kill(kill json item)
     """
     self.debugchannel = debugchannel
     self.starttime = timetime()
     kd = dc(kd)
     self.kd = kd
     self.killer = kd["Killer"]
     # Track killer
     for i in kd["Participants"]:
         if i["Id"] == kd["Killer"]["Id"]:
             self.killer = dc(i)
             break
     try:
         if not self.killer["DamageDone"]:
             self.killer["DamageDone"] = 0
     except KeyError:
         self.killer["DamageDone"] = 0
     # track victim
     self.victim = kd["Victim"]
     # Get the people who did the most damage
     try:
         self.assist = sorted(
             [i for i in kd["Participants"] if i["DamageDone"] > 0],
             key=lambda x: x["DamageDone"],
             reverse=True)[0]
     # Happens when the amount of participants is less than 1(even though I don't know how did it happen)
     except IndexError:
         self.assist = dc(self.killer)
     # Set type of solo kill or group kill
     # Is used to show if 3 people is shown on the final kill or 2
     self.solokill = (self.killer["Id"] == self.assist["Id"])
     # Set alliance names to the one similar in game
     if self.killer["AllianceName"]:
         self.killer["AllianceName"] = "[{}]".format(
             self.killer["AllianceName"])
     if self.assist["AllianceName"]:
         self.assist["AllianceName"] = "[{}]".format(
             self.assist["AllianceName"])
     if self.victim["AllianceName"]:
         self.victim["AllianceName"] = "[{}]".format(
             self.victim["AllianceName"])
     # Set victim guild if victim does not have a guild
     if not self.killer["GuildName"]:
         self.killer["GuildName"] = "- - - - -"
     if not self.assist["GuildName"]:
         self.assist["GuildName"] = "- - - - -"
     if not self.victim["GuildName"]:
         self.victim["GuildName"] = "- - - - -"
     self.totaldamage = int(
         sum([i["DamageDone"] for i in kd["Participants"]]))
     self.peoplegettingfame = len(
         [i for i in kd["GroupMembers"] if i["KillFame"] > 0])
     # Get the list of participants that dealt damage
     self.participants = sorted(
         [i for i in kd["Participants"] if i["DamageDone"] != 0],
         key=lambda x: x["DamageDone"],
         reverse=True)
     for i in self.participants:
         if i["AllianceName"] and not match(r"\[.*\]", i["AllianceName"]):
             i["AllianceName"] = "[{}]".format(i["AllianceName"])
     self.eventid = kd["EventId"]
     # Use regex and datetime module to get the time of killing in UTC
     dt = match(
         r"(\d{4})\-(\d{2})\-(\d{2})T(\d{2})\:(\d{2})\:(\d{2}\:*)\.(\d+)Z",
         kd["TimeStamp"])
     self.eventtime = datetime.datetime(int(dt.group(1)), int(dt.group(2)),
                                        int(dt.group(3)), int(dt.group(4)),
                                        int(dt.group(5)), int(dt.group(6)),
                                        int(dt.group(7)[:6]))
     if self.peoplegettingfame == 0:
         self.peoplegettingfame = len(kd["GroupMembers"])
         logging.warning("Peoplegetting fame error: {}".format(
             self.eventid))
     if self.totaldamage == 0:
         self.totaldamage = 100
         logging.warning("totaldamage error: {}".format(self.eventid))
     self.gw = 0
示例#22
0
def current_timestamp():
    return int(timetime())
示例#23
0
文件: core.py 项目: ceyzeriat/soif
def gen_seed():
    res = int(str((timetime() % 3600)/3600)[2:])
    return int(res*multiprocessingcurrent_process().pid % sysmaxint)
async def fetch_once(stockitem, fetch_time_internal, min_fetch_internal):
    global last_update_time

    def update_is_over(stockitem):
        sql.query_and_update('Tasks', 'taskid', stockitem.taskid, isover=1)

    async def send_email_warp(stockitem, fetched_price):
        # return send_mail_alert(stockitem,fetched_price)
        loop = asyncio.get_running_loop()
        if QQ_ALERT:
            loop.create_task(
                send_qq_alert(None, stockitem.stocknum, stockitem.incdesc,
                              stockitem.targetprice, fetched_price,
                              stockitem.remarks))
        return await loop.run_in_executor(
            thread_pool,
            partial(send_mail_alert, None, stockitem.stocknum,
                    stockitem.incdesc, stockitem.targetprice, fetched_price,
                    stockitem.remarks))

    async def result_handler(stockitem, fetched_price):
        if DEBUG:
            print('###################')
            print(stockitem, fetched_price)
            print('###################')

        __last_update_time = str(get_time_string_east8())
        sql.query_and_update('Tasks',
                             'taskid',
                             stockitem.taskid,
                             currentprice=fetched_price,
                             lastupdatetime=__last_update_time)
        if stockitem.incdesc == 0:
            if fetched_price >= stockitem.targetprice:
                update_is_over(stockitem)
                loop = asyncio.get_running_loop()
                rv = await send_email_warp(stockitem, fetched_price)
                return True
            else:
                return False
        else:
            if fetched_price <= stockitem.targetprice:
                update_is_over(stockitem)
                rv = await send_email_warp(stockitem, fetched_price)
                return True
            else:
                return False

    fetch_times = fetch_time_internal // min_fetch_internal
    url, bias_, return_met_ = using_api(stockitem.stocknum)
    for fetch_time in range(fetch_times):
        if DEBUG:
            sleep_time = 0
        else:
            sleep_time = random.randint(0, min_fetch_internal)
        sleep_time_after = min_fetch_internal - sleep_time
        await asyncio.sleep(sleep_time)
        st_time = timetime()
        fetched_price = await single_fetch(url, bias_, return_met_)
        if fetched_price == None:
            return
        res = await result_handler(stockitem, fetched_price)
        if res == True:
            return
        fetch_cost_time = timetime() - st_time
        sleep_time_after = max(sleep_time_after - fetch_cost_time - 0.1, 0)
        await asyncio.sleep(sleep_time_after)
        last_update_time = str(get_time_string_east8())