<s> from tapiriik . database import ratelimit as rl_db <EOL> from pymongo . read_preferences import ReadPreference <EOL> from datetime import datetime , timedelta <EOL> import math <EOL> class RateLimitExceededException ( Exception ) : <EOL> pass <EOL> class RateLimit : <EOL> def Limit ( key ) : <EOL> current_limits = rl_db . limits . find ( { "<STR_LIT>" : key } , { "<STR_LIT>" : <NUM_LIT:1> , "<STR_LIT>" : <NUM_LIT:1> } ) <EOL> for limit in current_limits : <EOL> if limit [ "<STR_LIT>" ] < limit [ "<STR_LIT>" ] : <EOL> raise RateLimitExceededException ( ) <EOL> rl_db . limits . update ( { "<STR_LIT>" : key } , { "<STR_LIT>" : { "<STR_LIT>" : <NUM_LIT:1> } } , multi = True ) <EOL> def Refresh ( key , limits ) : <EOL> midnight = datetime . combine ( datetime . utcnow ( ) . date ( ) , datetime . min . time ( ) ) <EOL> time_since_midnight = ( datetime . utcnow ( ) - midnight ) <EOL> rl_db . limits . remove ( { "<STR_LIT>" : key , "<STR_LIT>" : { "<STR_LIT>" : datetime . utcnow ( ) } } ) <EOL> current_limits = list ( rl_db . limits . with_options ( read_preference = ReadPreference . PRIMARY ) . find ( { "<STR_LIT>" : key } , { "<STR_LIT>" : <NUM_LIT:1> } ) ) <EOL> missing_limits = [ x for x in limits if x [ <NUM_LIT:0> ] . total_seconds ( ) not in [ limit [ "<STR_LIT>" ] for limit in current_limits ] ] <EOL> for limit in missing_limits : <EOL> window_start = midnight + timedelta ( seconds = math . floor ( time_since_midnight . total_seconds ( ) / limit [ <NUM_LIT:0> ] . total_seconds ( ) ) * limit [ <NUM_LIT:0> ] . total_seconds ( ) ) <EOL> window_end = window_start + limit [ <NUM_LIT:0> ] <EOL> rl_db . limits . insert ( { "<STR_LIT>" : key , "<STR_LIT>" : <NUM_LIT:0> , "<STR_LIT>" : limit [ <NUM_LIT:0> ] . total_seconds ( ) , "<STR_LIT>" : limit [ <NUM_LIT:1> ] , "<STR_LIT>" : window_end } ) </s>
