예제 #1
0
async def test_start_end_channel_incr(interface):
    await guild.system_channel.send(me_command)
    prev_stats = await utilities.get_user_stats(redis_client, bot_id, timepoint=timepoint)
    voice_channel = [channel for channel in guild.voice_channels if "screen/cam" in channel.name][1]
    voice_client = await voice_channel.connect()
    start_channel_time = utilities.get_time()
    utilities.sleep(time_to_stay)
    await voice_client.disconnect()
    end_channel_time = utilities.get_time()
    await guild.system_channel.send(me_command)
    utilities.sleep(discord_delay)
    cur_stats = await utilities.get_user_stats(redis_client, bot_id, timepoint=timepoint)
    # TODO test - use fields to check description?
    # reply = await guild.system_channel.history(limit=1).flatten()[0].embeds[0].description
    assert (utilities.check_stats_diff(prev_stats, cur_stats, time_to_stay, 1, redis_tolerance))

    # Check SQL
    records = sqlalchemy_session.query(Action) \
        .filter(Action.user_id == bot_id) \
        .filter(Action.category.in_(["end channel", "start channel"])) \
        .order_by(Action.creation_time.desc()).limit(2).all()
    records.reverse()

    assert (records[0].category == "start channel")
    assert (records[0].detail == records[1].detail == voice_channel.id)
    assert (records[0].creation_time - start_channel_time <= db_tolerance)
    assert (records[1].creation_time - end_channel_time <= db_tolerance)
예제 #2
0
    def __init__(self, bot):
        self.bot = bot
        self.guild = None
        self.role_name_to_obj = None
        self.role_name_to_info = None
        self.supporter_role = None

        self.command_channels = utilities.config[
            ("test_" if os.getenv("mode") == "test" else "") +
            "command_channels"]
        self.announcement_channel = utilities.config[
            ("test_" if os.getenv("mode") == "test" else "") +
            "announcement_channel"]
        # TODO fix when files not existent
        self.data_change_logger = utilities.get_logger(
            "study_executor_data_change", "data_change.log")
        self.time_counter_logger = utilities.get_logger(
            "study_executor_time_counter", "discord.log")
        self.heartbeat_logger = utilities.get_logger(
            "study_executor_heartbeat", "heartbeat.log")
        self.redis_client = utilities.get_redis_client()
        engine = utilities.get_engine()
        Session = sessionmaker(bind=engine)
        self.sqlalchemy_session = Session()
        self.timezone_session = utilities.get_timezone_session()
        self.make_heartbeat.start()
        self.birthtime = utilities.get_time()
예제 #3
0
    def sync_db(self, user_id, channel, category_type, category_offset):
        cur_time = utilities.get_time()
        categories = [i + " " + category_type for i in ["end", "start"]]
        cur_category = categories[category_offset]
        last_record = self.get_last_record(user_id, categories)

        # Heuristic data recovery if users have voice_state_update when the bot is down
        # See all possible scenarios in test_bot.py
        if last_record:
            # For case:
            # last: start id_1
            # cur: end id_2
            if last_record.detail != channel.id and categories.index(
                    last_record.category):
                # Add end for last
                last_category_offset = categories.index(last_record.category)
                cur_time += timedelta(microseconds=1)
                record = Action(user_id=user_id,
                                category=categories[1 - last_category_offset],
                                detail=last_record.detail,
                                creation_time=cur_time)
                self.sqlalchemy_session.add(record)

                if category_offset == 0:
                    # Add start for cur
                    # A bit inelegant when a user with video on switches to another channel
                    cur_time += timedelta(microseconds=1)
                    record = Action(user_id=user_id,
                                    category=categories[last_category_offset],
                                    detail=channel.id,
                                    creation_time=cur_time)
                    self.sqlalchemy_session.add(record)
            # For case:
            # start(end) id_1
            # start(end) id_1

            # end id_1
            # end id_2
            elif last_record.category == cur_category:
                cur_time += timedelta(microseconds=1)
                record = Action(user_id=user_id,
                                category=categories[1 - category_offset],
                                detail=last_record.detail,
                                creation_time=cur_time)
                self.sqlalchemy_session.add(record)

        cur_time += timedelta(microseconds=1)

        # Users might jump to non-monitored channels
        if check_categories(channel):
            record = Action(user_id=user_id,
                            category=cur_category,
                            detail=channel.id,
                            creation_time=cur_time)
            self.sqlalchemy_session.add(record)

        utilities.commit_or_rollback(self.sqlalchemy_session)

        return last_record.creation_time if last_record else cur_time
예제 #4
0
    def handle_in_session(self, user_id, reset):
        """
        When a user issues commands, we want to show up-to-date info even if there is no "voice_state_update"
        """
        # after data recovery we should have a sensible start channel record
        last_record = self.get_last_record(user_id, ["start channel"])
        cur_time = utilities.get_time()
        last_record_time = last_record.creation_time if last_record else cur_time

        rank_categories = utilities.get_rank_categories(string=False)
        rank_categories_val = list(rank_categories.values())
        string_rank_categories = list(
            utilities.get_rank_categories(string=True).values())
        in_session_names = [
            "in_session_" + str(in_session)
            for in_session in string_rank_categories[0]
        ]
        category_key_names = string_rank_categories[
            0] + string_rank_categories[1:]
        in_session_incrs = []

        for in_session, in_session_name in zip(rank_categories_val[0],
                                               in_session_names):
            in_session_time = self.redis_client.hget(in_session_name, user_id)
            in_session_time = float(in_session_time) if in_session_time else 0
            base_time = max(last_record_time, in_session)
            incr = utilities.timedelta_to_hours(cur_time -
                                                base_time) - in_session_time
            # Max necessary since an enter channel (or other voice status change) update/sync might be called earlier than the exit one
            incr = max(incr, 0)
            in_session_incrs.append(incr)
            new_val = 0 if reset else incr + in_session_time
            self.redis_client.hset(in_session_name, user_id, new_val)

        # standard incr is what gets used for monthly and weekly. In other words, official incr is one of the sets of stats
        in_session_std_time_name = f"in_session_std"
        in_session_std_time = self.redis_client.hget(in_session_std_time_name,
                                                     user_id)
        in_session_std_time = float(
            in_session_std_time) if in_session_std_time else 0
        std_incr = utilities.timedelta_to_hours(
            cur_time - last_record_time) - in_session_std_time

        neg_msg = f"std_incr Negative: {std_incr}\n" if std_incr < 0 else ""
        std_incr = max(std_incr, 0)
        in_session_std_time = 0 if reset else std_incr + in_session_std_time
        self.redis_client.hset(in_session_std_time_name, user_id,
                               in_session_std_time)

        monthly_now, all_time_now = utilities.increment_studytime(
            category_key_names,
            self.redis_client,
            user_id,
            in_session_incrs=in_session_incrs,
            std_incr=std_incr)
        log_msg = f'{utilities.get_time()}\n{neg_msg}monthly_now: {monthly_now}\nall_time_now: {all_time_now}\nincr: {std_incr}\ncur_time: {cur_time}\nlast_record_time: {last_record_time}\npast_in_session_time: {in_session_std_time}\nuser_id: {user_id}'
        self.data_change_logger.info(log_msg)
예제 #5
0
    def sync_db(self, user_id, channel, category_type, category_offset):
        cur_time = utilities.get_time()
        categories = [i + " " + category_type for i in ["end", "start"]]
        cur_category = categories[category_offset]
        last_record = self.get_last_record(user_id, categories)

        # data recovery
        if last_record:
            # For case:
            # last: start id_1
            # cur: end id_2
            if last_record.detail != channel.id and categories.index(
                    last_record.category):
                # Add end for last
                last_category_offset = categories.index(last_record.category)
                cur_time += timedelta(microseconds=1)
                record = Action(user_id=user_id,
                                category=categories[1 - last_category_offset],
                                detail=last_record.detail,
                                creation_time=cur_time)
                self.sqlalchemy_session.add(record)
                if category_offset == 0:
                    # Add start for cur
                    # A bit inelegant when a user with video on switches to another channel
                    cur_time += timedelta(microseconds=1)
                    record = Action(user_id=user_id,
                                    category=categories[last_category_offset],
                                    detail=channel.id,
                                    creation_time=cur_time)
                    self.sqlalchemy_session.add(record)
            # For case:
            # start(end) id_1
            # start(end) id_1

            # end id_1
            # end id_2
            elif last_record.category == cur_category:
                cur_time += timedelta(microseconds=1)
                record = Action(user_id=user_id,
                                category=categories[1 - category_offset],
                                detail=last_record.detail,
                                creation_time=cur_time)
                self.sqlalchemy_session.add(record)

        cur_time += timedelta(microseconds=1)
        record = Action(user_id=user_id,
                        category=cur_category,
                        detail=channel.id,
                        creation_time=cur_time)
        self.sqlalchemy_session.add(record)
        utilities.commit_or_rollback(self.sqlalchemy_session)

        return last_record.creation_time if last_record else cur_time
예제 #6
0
    def handle_in_session(self, user_id, reset):
        # after data recovery we should have a sensible start channel record
        last_record = self.get_last_record(user_id, ["start channel"])
        cur_time = utilities.get_time()
        last_record_time = last_record.creation_time if last_record else cur_time

        rank_categories = utilities.get_rank_categories(string=False)
        rank_categories_val = list(rank_categories.values())
        string_rank_categories = list(
            utilities.get_rank_categories(string=True).values())
        in_session_names = [
            "in_session_" + str(in_session)
            for in_session in string_rank_categories[0]
        ]
        category_key_names = string_rank_categories[
            0] + string_rank_categories[1:]
        in_session_incrs = []
        std_incr = None

        # TODO optimize: most values here will be the same and this is the bottleneck
        for in_session, in_session_name in zip(rank_categories_val[0],
                                               in_session_names):
            past_in_session_time = self.redis_client.hget(
                in_session_name, user_id)
            past_in_session_time = float(
                past_in_session_time) if past_in_session_time else 0
            base_time = max(last_record_time, in_session)
            incr = utilities.timedelta_to_hours(
                cur_time - base_time) - past_in_session_time
            if in_session_name[-8:] == str(
                    utilities.config["business"]["update_time"]) + ":00:00":
                std_incr = incr
                prev_std_incr_name = "daily_" + str(in_session -
                                                    timedelta(days=1))
                prev_std_incr = self.redis_client.hget(
                    "in_session_" + prev_std_incr_name, user_id)
                prev_std_incr = float(prev_std_incr) if prev_std_incr else 0
                if prev_std_incr:
                    std_incr += prev_std_incr
                    self.redis_client.hset("in_session_" + prev_std_incr_name,
                                           user_id, 0)
            in_session_incrs.append(incr)
            new_val = 0 if reset else incr + past_in_session_time
            self.redis_client.hset(in_session_name, user_id, new_val)

        utilities.increment_studytime(category_key_names,
                                      self.redis_client,
                                      user_id,
                                      in_session_incrs=in_session_incrs,
                                      std_incr=std_incr)
예제 #7
0
    def __init__(self, bot):
        self.bot = self.client = bot
        self.guild = None
        self.role_objs = None
        self.role_names = None
        self.supporter_role = None

        self.data_change_logger = utilities.get_logger(
            "study_executor_data_change", "data_change.log")
        self.time_counter_logger = utilities.get_logger(
            "study_executor_time_counter", "discord.log")
        self.redis_client = utilities.get_redis_client()
        engine = utilities.get_engine()
        Session = sessionmaker(bind=engine)
        self.sqlalchemy_session = Session()
        self.timezone_session = utilities.get_timezone_session()
        self.birthtime = utilities.get_time()
예제 #8
0
    def __init__(self, bot):
        self.bot = bot
        self.guild = None
        self.role_objs = None
        self.role_name_to_obj = None
        self.supporter_role = None

        # TODO fix when files not existent
        self.time_counter_logger = utilities.get_logger(
            "study_executor_time_counter", "discord.log")
        self.heartbeat_logger = utilities.get_logger(
            "study_executor_heartbeat", "heartbeat.log")
        self.redis_client = utilities.get_redis_client()
        engine = utilities.get_engine()
        Session = sessionmaker(bind=engine)
        self.sqlalchemy_session = Session()
        self.timezone_session = utilities.get_timezone_session()
        self.make_heartbeat.start()
        self.birthtime = utilities.get_time()
예제 #9
0
 async def on_command_error(self, ctx, exception):
     print(utilities.get_time(), exception)
     await ctx.send(f"{exception}\nTry ~help?")
예제 #10
0
    return [float(row[1]), float(row[2])]


path = os.path.join(os.path.dirname(__file__), '..', '../routes/ASC2018.csv')
total_time = 0  #in minutes
with open(path, 'r') as asc2018:
    next(asc2018)
    total_time = 0
    p2 = None
    p1 = getCoordinates(asc2018)  #[long, lat]
    f = open('predictions.csv', 'a')
    for i in range(16):
        while total_time < 30:
            p2 = getCoordinates(asc2018)
            d = find_distance(p1[0], p1[1], p2[0], p2[1])
            total_time += get_time(d) * 60  #get time in mins
            p1 = p2

        #PRINTING COORDINATES USED
        print(p1)
        print(p2)

        #get prediction forecast (API CALL)
        raw_forecast = get_radiation_data(p2[0], p2[1], api_key)
        future_forecast = [i, raw_forecast['forecasts'][1]['ghi']]
        #current time
        t = time.localtime()
        current_time = time.strftime("%H:%M:%S", t)
        print(current_time)

        #wait 30 minutes
예제 #11
0
logger = utilities.get_logger("main", "heartbeat.log")

proc = None
line = utilities.get_last_line()
# TODO: fix - Dangerous - need to make sure it's our process
utilities.kill_last_process(line)

while True:
    try:
        line = utilities.get_last_line()
        last_time = utilities.get_last_time(line)
        max_diff_var_name = ("test_" if os.getenv("mode") == "test" else
                             "") + "heart_attack_interval_sec"
        max_diff_sec = int(os.getenv(max_diff_var_name))
        max_diff = timedelta(seconds=max_diff_sec)

        if (not last_time) or utilities.get_time() - last_time > max_diff:
            # Process has died. Restart it
            proc = subprocess.Popen(['python3', './time_counter.py'])
            logger.info(f"{utilities.get_time()} birth with pid {proc.pid}")

        sleep(60 if os.getenv("mode") != "test" else max_diff_sec)
    except Exception as e:
        print(e)
        # This does not catch exceptions from child processes!!
        if proc:
            proc.kill()
        logger.info(f"{utilities.get_time()} graceful death")

        break
예제 #12
0
def main():
    print(utilities.get_time())