Ejemplo n.º 1
0
def manage_user(uid, user_grade, user_class, req_id, debugging):
    log.info("[#%s] manage_user@modules/user.py: Started Managing User Info" % req_id)
    try:
        with open(path, encoding="utf-8") as data_file:
            enc = hashlib.sha256()
            enc.update(uid.encode("utf-8"))
            enc_uid = enc.hexdigest()
            data = json.load(data_file)
        if debugging:
            print(data)
        if enc_uid in data:  # 사용자 정보 있을 때
            if data[enc_uid][0] == user_grade and data[enc_uid][1] == user_class:  # 사용자 정보 똑같을 때
                log.info("[#%s] manage_user@modules/user.py: Same" % req_id)
                return "Same"
            else:  # 사용자 정보 있고 같지도 않을 때 - 업데이트 (삭제 후 재생성)
                del data[enc_uid]
                if debugging:
                    print("DEL USER")
                log.info("[#%s] manage_user@modules/user.py: Updated" % req_id)
                return_msg = "Updated"
        else:  # 사용자 정보 없을 때 - 생성
            log.info("[#%s] manage_user@modules/user.py: Registered" % req_id)
            return_msg = "Registered"
        user_data = [int(user_grade), int(user_class)]
        data[enc_uid] = user_data
        with open(path, "w", encoding="utf-8") as write_file:
            json.dump(data, write_file, ensure_ascii=False, indent="\t")
            log.info("[#%s] manage_user@modules/user.py: Succeeded" % req_id)
            return return_msg
    except Exception:
        log.err("[#%s] manage_user@modules/user.py: Failed" % req_id)
        return Exception
Ejemplo n.º 2
0
def meal(reqdata, req_id, debugging):
    log.info("[#%s] meal@modules/skill.py: New Request" % req_id)
    try:
        sys_date = json.loads(
            json.loads(reqdata)["action"]["params"]["sys_date"])[
                "date"]  # 날짜 가져오기
    except Exception:
        log.err("[#%s] meal@modules/skill.py: Error while Parsing Request" %
                req_id)
        return skill("오류가 발생했습니다.\n요청 ID: " + req_id)
    try:
        # 년월일 파싱
        year = datetime.datetime.strptime(sys_date, "%Y-%m-%d").timetuple()[0]
        month = datetime.datetime.strptime(sys_date, "%Y-%m-%d").timetuple()[1]
        date = datetime.datetime.strptime(sys_date, "%Y-%m-%d").timetuple()[2]
        wday = datetime.datetime.strptime(sys_date, "%Y-%m-%d").timetuple()[6]
    except ValueError:  # 파싱중 값오류 발생시
        log.err("[#%s] meal@modules/skill.py: ValueError while Parsing Date" %
                req_id)
        return skill("오류가 발생했습니다.\n요청 ID: " + req_id)
    if debugging:
        print(sys_date)
        print(year)
        print(month)
        print(date)
        print(wday)
    return skill(meal_core(year, month, date, wday, req_id, debugging))
Ejemplo n.º 3
0
def weather(date_ko, req_id, debugging):
    global weather_data
    now = datetime.datetime.now()
    log.info("[#%s] weather@modules/getData.py: Started Fetching Weather Data" % req_id)

    # 날씨 파싱 후 캐싱
    def parse():
        global weather_data

        log.info("[#%s] weather@modules/getData.py: Started Parsing Weather Data" % req_id)

        weather_data = weatherParser.parse(req_id, debugging)

        # 지금의 날짜와 시간까지만 취함
        weather_data["Timestamp"] = int(datetime.datetime(now.year, now.month, now.day, now.hour).timestamp())

        with open('data/cache/weather.json', 'w',
                  encoding="utf-8") as make_file:  # 캐시 만들기
            json.dump(weather_data, make_file, ensure_ascii=False, indent="\t")
            print("File Created")

        log.info("[#%s] weather@modules/getData.py: Succeeded" % req_id)

    if os.path.isfile('data/cache/weather.json'):  # 캐시 있으면
        try:
            log.info("[#%s] weather@modules/getData.py: Read Data in Cache" % req_id)
            with open('data/cache/weather.json', encoding="utf-8") as data_file:  # 캐시 읽기
                data = json.load(data_file, object_pairs_hook=OrderedDict)
        except Exception:  # 캐시 읽을 수 없으면
            try:
                os.remove('data/cache/weather.json')  # 캐시 삭제
            except Exception:
                log.err("[#%s] weather@modules/getData.py: Failed to Delete Cache" % req_id)
                return "측정소 또는 서버 오류입니다."
            parse()  # 파싱
        # 캐시 유효하면
        if now - datetime.datetime.fromtimestamp(data["Timestamp"]) < datetime.timedelta(hours=1):
            global weather_data
            log.info("[#%s] weather@modules/getData.py: Use Data in Cache" % req_id)
            weather_data = data
        else:  # 캐시 무효하면
            log.info("[#%s] weather@modules/getData.py: Cache Expired" % req_id)
            parse()  # 파싱
    else:  # 캐시 없으면
        log.info("[#%s] weather@modules/getData.py: No Cache" % req_id)
        parse()  # 파싱

    return_data = ("🌡️ %s 최소/최대 기온: %s℃/%s℃\n\n"
                   "등굣길 예상 날씨: %s\n"
                   "🌡️ 기온: %s℃\n"
                   "🌦️ 강수 형태: %s\n"
                   "❔ 강수 확률: %s%%\n"
                   "💧 습도: %s%%"
                   % (date_ko, weather_data['temp_min'], weather_data['temp_max'], weather_data['sky'],
                      weather_data['temp'], weather_data['pty'], weather_data['pop'], weather_data['reh'])
                   )

    log.info("[#%s] weather@modules/getData.py: Succeeded" % req_id)

    return return_data
Ejemplo n.º 4
0
 def f_tt():
     global briefing_tt
     tt_grade = str()
     tt_class = str()
     try:
         uid = json.loads(reqdata)["userRequest"]["user"]["id"]
         user_data = user.get_user(uid, req_id, debugging)  # 사용자 정보 불러오기
         tt_grade = user_data[0]
         tt_class = user_data[1]
     except Exception:
         log.err(
             "[#%s] briefing@modules/skill.py: Failed to Fetch Timetable" %
             req_id)
         briefing_tt = "시간표 조회 중 오류가 발생했습니다."
     if tt_grade is not None or tt_class is not None:  # 사용자 정보 있을 때
         tt = getData.tt(tt_grade, tt_class, date.year, date.month,
                         date.day, req_id, debugging)
         if tt == "등록된 데이터가 없습니다.":
             briefing_tt = "등록된 시간표가 없습니다."
         else:
             briefing_tt = "%s 시간표:\n%s" % (date_ko, tt.split('):\n\n')[1]
                                            )  # 헤더부분 제거
     else:
         log.info("[#%s] briefing@modules/skill.py: Non-Registered User" %
                  req_id)
         briefing_tt = "등록된 사용자만 시간표를 볼 수 있습니다."
Ejemplo n.º 5
0
def commits(req_id, debugging):
    # GitHub API 사용
    # API 사양은 https://developer.github.com/v3/repos/commits/#list-commits-on-a-repository 참조
    try:
        response = (
            urllib.request.urlopen(url="https://api.github.com/repos/hgyoseo/hdmeal/commits").read().decode('utf-8')
        )
        data = json.loads(response)
    except Exception as error:
        if debugging:
            print(error)
        log.err("[#%s] commits@modules/getData.py: Failed to Parse Commits" % req_id)
        return error

    # 마지막 커밋이 일어난 시간를 파싱함
    # 시간은 UTC 기준, datetime에서 인식할 수 있게 하기 위해 Z를 떼고 9시간을 더해 한국 표준시로 변환
    updated_at_datetime = (datetime.datetime.fromisoformat(data[0]["commit"]["committer"]["date"].replace("Z", ""))
                           + datetime.timedelta(hours=9))
    updated_at = "%s년 %s월 %s일 %s시 %s분" % (
        updated_at_datetime.year, updated_at_datetime.month, updated_at_datetime.day,
        updated_at_datetime.hour, updated_at_datetime.minute
    )
    # 최근 5개 커밋의 메시지 가져오기
    messages = list(map(lambda loc: data[loc]["commit"]["message"], range(5)))
    # 리스트의 0번에 마지막 커밋 시간 삽입
    messages.insert(0, updated_at)
    log.info("[#%s] commits@modules/getData.py: Succeeded" % req_id)
    return messages
Ejemplo n.º 6
0
def user_settings_rest_delete(req, req_id, debugging):
    try:
        delete_user(decoded['uid'], req_id, debugging)
    except Exception as error:
        log.err("[#%s] user_settings_rest_delete@modules/user.py: %s" % (req_id, error))
        return errors["ServerError"]
    return {'message': "삭제했습니다."}
Ejemplo n.º 7
0
 def inner(req, req_id, debugging):
     if "uid" in decoded:
         try:
             user = get_user(decoded['uid'], req_id, debugging)
         except Exception as error:
             log.err("[#%s] user_settings_rest_get@modules/user.py: %s" % (req_id, error))
             return errors["ServerError"]
         return {'token': token, 'classes': list(range(1, classes + 1)), 'uid': decoded["uid"],
                 'current_grade': user[0], 'current_class': user[1]}
     else:
         return errors["InvalidToken"]
Ejemplo n.º 8
0
def tt(reqdata, req_id, debugging):
    log.info("[#%s] tt@modules/skill.py: New Request" % req_id)
    try:
        tt_grade = json.loads(reqdata)["action"]["params"]["Grade"]  # 학년 파싱
    except Exception:
        log.err("[#%s] tt@modules/skill.py: Error while Parsing Grade" %
                req_id)
        return skill("오류가 발생했습니다.\n요청 ID: " + req_id)
    try:
        tt_class = json.loads(reqdata)["action"]["params"]["Class"]  # 반 파싱
    except Exception:
        log.err("[#%s] tt@modules/skill.py: Error while Parsing Class" %
                req_id)
        return skill("오류가 발생했습니다.\n요청 ID: " + req_id)
    try:
        sys_date = json.loads(
            json.loads(reqdata)["action"]["params"]["sys_date"])[
                "date"]  # 날짜 파싱
    except Exception:
        log.err("[#%s] tt@modules/skill.py: Error while Parsing Date" % req_id)
        return skill("오류가 발생했습니다.\n요청 ID: " + req_id)
    try:
        date = datetime.datetime.strptime(sys_date, "%Y-%m-%d")
    except ValueError:  # 값오류 발생시
        log.err("[#%s] tt@modules/skill.py: ValueError while Parsing Date" %
                req_id)
        return skill("오류가 발생했습니다.\n요청 ID: " + req_id)
    if debugging:
        print(tt_grade)
        print(tt_class)
    msg = getData.tt(tt_grade, tt_class, date.year, date.month, date.day,
                     req_id, debugging)
    return skill(msg)
Ejemplo n.º 9
0
def user_settings_rest_post(req, req_id, debugging):
    if "user_grade" in req_data and "user_class" in req_data:
        user_grade = int(req_data["user_grade"])
        user_class = int(req_data["user_class"])
        if 0 < user_grade < 4 and 0 < user_class <= classes:
            try:
                manage_user(decoded['uid'], user_grade, user_class, req_id, debugging)
            except Exception as error:
                log.err("[#%s] user_settings_rest_post@modules/user.py: %s" % (req_id, error))
                return errors["ServerError"]
            return {'message': "저장했습니다."}
        else:
            return errors["InvalidRequest"]
    else:
        return errors["InvalidRequest"]
Ejemplo n.º 10
0
 def parse():
     log.info("[#%s] wtemp@modules/getData.py: Started Parsing Water Temperature Data" % req_id)
     try:
         global date, temp
         parser = WTempParser.get(req_id, debugging)
         date = parser[0]
         temp = parser[1]
     except Exception:
         log.err("[#%s] wtemp@modules/getData.py: Failed to Fetch Water Temperature Data" % req_id)
         return "측정소 또는 서버 오류입니다."
     if not temp.isalpha():  # 무효값 걸러냄(값이 유효할 경우에만 캐싱)
         with open('data/cache/wtemp.json', 'w',
                   encoding="utf-8") as make_file:  # 캐시 만들기
             json.dump({"timestamp": int(date.timestamp()), "temp": temp}, make_file, ensure_ascii=False, indent="\t")
             print("File Created")
             temp = temp + "°C"
     log.info("[#%s] wtemp@modules/getData.py: Succeeded" % req_id)
Ejemplo n.º 11
0
def purge_cache(reqdata, req_id, debugging):
    log.info("[#%s] purge_cache@modules/skill.py: New Request" % req_id)
    # 사용자 ID 가져오고 검증
    uid = json.loads(reqdata)["userRequest"]["user"]["id"]
    if user.auth_admin(uid, req_id, debugging):
        if cache.purge(req_id, debugging)["status"] == "OK":  # 삭제 실행, 결과 검증
            msg = "캐시를 비웠습니다."
        else:
            log.err(
                "[#%s] purge_cache@modules/skill.py: Failed to Purge Cache" %
                req_id)
            msg = "삭제에 실패하였습니다. 오류가 발생했습니다."
    else:
        log.info("[#%s] purge_cache@modules/skill.py: Non-Authorized User" %
                 req_id)
        msg = "사용자 인증에 실패하였습니다.\n당신의 UID는 %s 입니다." % uid
    return skill(msg)
Ejemplo n.º 12
0
def purge(req_id, debugging):
    dict_data = OrderedDict()
    try:
        file_list = [
            file for file in os.listdir("data/cache/")
            if file.endswith(".json")
        ]
        for file in file_list:
            os.remove("data/cache/" + file)
    except Exception as error:
        log.err("[#%s] purge@modules/cache.py: Failed" % req_id)
        if debugging:
            dict_data["status"] = error
        dict_data["status"] = "Error"
        return dict_data
    dict_data["status"] = "OK"
    log.info("[#%s] purge@modules/cache.py: Succeeded" % req_id)
    return dict_data
Ejemplo n.º 13
0
def get(req_id, debugging):
    log.info("[#%s] get@modules/WTempParser.py: Started Parsing Water Temperature" % req_id)
    try:
        url = urllib.request.urlopen("http://koreawqi.go.kr/wQSCHomeLayout_D.wq?action_type=T")
    except Exception as error:
        if debugging:
            print(error)
        log.err("[#%s] get@modules/WTempParser.py: Failed" % req_id)
        return error
    data = BeautifulSoup(url, 'html.parser')
    # 측정일시 파싱
    date = data.find('span', class_='data').get_text().split('"')[1]
    date = int(date[0:4]), int(date[4:6]), int(date[6:8])
    time = int(data.find('span', class_='data').get_text().split('"')[3])
    measurement_date = datetime.datetime(date[0], date[1], date[2], time)
    # 수온 파싱
    wtemp = data.find('tr', class_='site_S01004').get_text()  # 구리측정소 사용
    wtemp = wtemp.replace("구리", "").strip()
    log.info("[#%s] get@modules/WTempParser.py: Succeeded" % req_id)
    return measurement_date, wtemp
Ejemplo n.º 14
0
def delete_user(uid, req_id, debugging):
    log.info("[#%s] delete_user@modules/user.py: Started Deleting User Info" % req_id)
    try:
        with open(path, encoding="utf-8") as data_file:
            enc = hashlib.sha256()
            enc.update(uid.encode("utf-8"))
            enc_uid = enc.hexdigest()
            data = json.load(data_file)
        if enc_uid in data:  # 사용자 정보 있을 때
            if debugging:
                print("DEL USER")
            del data[enc_uid]
        else:  # 사용자 정보 없을 때
            log.info("[#%s] delete_user@modules/user.py: No User Info" % req_id)
            return "NotExist"
        with open(path, "w", encoding="utf-8") as write_file:
            json.dump(data, write_file, ensure_ascii=False, indent="\t")
            log.info("[#%s] delete_user@modules/user.py: Succeeded" % req_id)
            return "Deleted"
    except Exception:
        log.err("[#%s] delete_user@modules/user.py: Failed" % req_id)
        return Exception
Ejemplo n.º 15
0
def user_settings_web(reqdata, jwt_secret, req_id, debugging):
    url = os.getenv("SETTINGS_URL")
    try:
        uid = json.loads(reqdata)["userRequest"]["user"]["id"]
    except Exception:
        log.err("[#%s] briefing@modules/skill.py: Failed to Fetch Timetable" %
                req_id)
        return skill_simpletext("토큰 생성 중 오류가 발생했습니다.")
    encoded = jwt.encode(
        {
            'exp':
            datetime.datetime.utcnow() + datetime.timedelta(seconds=300),
            'uid': uid
        },
        jwt_secret,
        algorithm='HS384')
    return {
        'version': '2.0',
        'template': {
            'outputs': [{
                "basicCard": {
                    "title":
                    "내 정보 관리",
                    "description":
                    "아래 버튼을 클릭해 관리 페이지로 접속해 주세요.\n"
                    "링크는 5분 뒤 만료됩니다.",
                    "buttons": [{
                        "action":
                        "webLink",
                        "label":
                        "내 정보 관리",
                        "webLinkUrl":
                        url + "?token=" + encoded.decode("UTF-8")
                    }]
                }
            }]
        }
    }
Ejemplo n.º 16
0
def delete_user(reqdata, req_id, debugging):
    log.info("[#%s] delete_user@modules/skill.py: New Request" % req_id)
    try:
        uid = json.loads(reqdata)["userRequest"]["user"]["id"]  # UID 파싱
    except Exception:
        log.err("[#%s] delete_user@modules/skill.py: Error while Parsing UID" %
                req_id)
        return skill("오류가 발생했습니다.\n요청 ID: " + req_id)
    if debugging:
        print(uid)
    req = user.delete_user(uid, req_id, debugging)
    if req == "NotExist":
        log.info("[#%s] delete_user@modules/skill.py: User does Not Exist" %
                 req_id)
        msg = "존재하지 않는 사용자입니다."
    elif req == "Deleted":
        log.info("[#%s] delete_user@modules/skill.py: Deleted" % req_id)
        msg = "삭제에 성공했습니다."
    else:
        log.err(
            "[#%s] delete_user@modules/skill.py: Failed to Process Request" %
            req_id)
        return skill("오류가 발생했습니다.\n요청 ID: " + req_id)
    return skill(msg)
Ejemplo n.º 17
0
def manage_user(reqdata, req_id, debugging):
    log.info("[#%s] manage_user@modules/skill.py: New Request" % req_id)
    try:
        user_grade = json.loads(reqdata)["action"]["params"]["Grade"]  # 학년 파싱
    except Exception:
        log.err(
            "[#%s] manage_user@modules/skill.py: Error while Parsing Grade" %
            req_id)
        return skill("오류가 발생했습니다.\n요청 ID: " + req_id)
    try:
        user_class = json.loads(reqdata)["action"]["params"]["Class"]  # 반 파싱
    except Exception:
        log.err(
            "[#%s] manage_user@modules/skill.py: Error while Parsing Class" %
            req_id)
        return skill("오류가 발생했습니다.\n요청 ID: " + req_id)
    try:
        uid = json.loads(reqdata)["userRequest"]["user"]["id"]  # UID 파싱
    except Exception:
        log.err("[#%s] manage_user@modules/skill.py: Error while Parsing UID" %
                req_id)
        return skill("오류가 발생했습니다.\n요청 ID: " + req_id)
    if debugging:
        print(user_grade)
        print(user_class)
        print(uid)
    req = user.manage_user(uid, user_grade, user_class, req_id, debugging)
    if req == "Registered":
        log.info("[#%s] manage_user@modules/skill.py: Created" % req_id)
        msg = "등록에 성공했습니다."
    elif req == "Same":
        log.info("[#%s] manage_user@modules/skill.py: Same" % req_id)
        msg = "저장된 정보와 수정할 정보가 같아 수정하지 않았습니다."
    elif req == "Updated":
        log.info("[#%s] manage_user@modules/skill.py: Updated" % req_id)
        msg = "수정되었습니다."
    else:
        log.err(
            "[#%s] manage_user@modules/skill.py: Failed to Process Request" %
            req_id)
        return skill("오류가 발생했습니다.\n요청 ID: " + req_id)
    return skill(msg)
Ejemplo n.º 18
0
def tt_registered(reqdata, req_id, debugging):
    log.info("[#%s] tt_registered@modules/skill.py: New Request" % req_id)
    try:
        uid = json.loads(reqdata)["userRequest"]["user"]["id"]
        user_data = user.get_user(uid, req_id, debugging)  # 사용자 정보 불러오기
        tt_grade = user_data[0]
        tt_class = user_data[1]
    except Exception:
        log.err(
            "[#%s] tt_registered@modules/skill.py: Error while Parsing Request"
            % req_id)
        return skill("오류가 발생했습니다.\n요청 ID: " + req_id)
    if tt_grade and tt_class:  # 사용자 정보 있을 때
        try:
            sys_date = json.loads(
                json.loads(reqdata)["action"]["params"]["sys_date"])[
                    "date"]  # 날짜 파싱
        except Exception:
            log.err(
                "[#%s] tt_registered@modules/skill.py: Error while Parsing Date"
                % req_id)
            return skill("오류가 발생했습니다.\n요청 ID: " + req_id)
        try:
            date = datetime.datetime.strptime(sys_date, "%Y-%m-%d")
        except ValueError:  # 값오류 발생시
            log.err(
                "[#%s] tt_registered@modules/skill.py: ValueError while Parsing Date"
                % req_id)
            return skill("오류가 발생했습니다.\n요청 ID: " + req_id)
        if debugging:
            print(tt_grade)
            print(tt_class)
        msg = getData.tt(tt_grade, tt_class, date.year, date.month, date.day,
                         req_id, debugging)
    else:
        log.info("[#%s] tt_registered@modules/skill.py: Non-Registered User" %
                 req_id)
        msg = "힉년/반 정보가 없습니다.\n먼저 내 정보 등록을 해 주시기 바랍니다."
    return skill(msg)
Ejemplo n.º 19
0
def schdl(reqdata, req_id, debugging):
    global msg
    log.info("[#%s] cal@modules/skill.py: New Request" % req_id)
    try:
        data = json.loads(reqdata)["action"]["params"]
    except Exception:
        log.err("[#%s] cal@modules/skill.py: Error while Parsing Request" %
                req_id)
        return skill("오류가 발생했습니다.\n요청 ID: " + req_id)

    # 특정일자 조회
    if "sys_date" in data:
        try:
            date = datetime.datetime.strptime(
                json.loads(data["sys_date"])["date"], "%Y-%m-%d")  # 날짜 파싱
        except Exception:
            log.err("[#%s] cal@modules/skill.py: Error while Parsing Date" %
                    req_id)
            return skill("오류가 발생했습니다.\n요청 ID: " + req_id)

        prsnt_schdl = getData.schdl(date.year, date.month, date.day, req_id,
                                    debugging)

        prsnt_schdl = prsnt_schdl
        if prsnt_schdl:
            msg = "%s-%s-%s(%s):\n%s" % (str(
                date.year).zfill(4), str(date.month).zfill(2), str(
                    date.day).zfill(2), wday(date), prsnt_schdl
                                         )  # YYYY-MM-DD(Weekday)
        else:
            msg = "일정이 없습니다."
    # 특정일자 조회 끝

    # 기간 조회
    elif "sys_date_period" in data:  # 기간

        body = str()

        try:
            start = json.loads(
                data["sys_date_period"])["from"]["date"]  # 시작일 파싱
            start = datetime.datetime.strptime(start, "%Y-%m-%d")
        except Exception:
            log.err(
                "[#%s] cal@modules/skill.py: Error while Parsing StartDate" %
                req_id)
            return skill("오류가 발생했습니다.\n요청 ID: " + req_id)
        try:
            end = json.loads(data["sys_date_period"])["to"]["date"]  # 종료일 파싱
            end = datetime.datetime.strptime(end, "%Y-%m-%d")
        except Exception:
            log.err("[#%s] cal@modules/skill.py: Error while Parsing EndDate" %
                    req_id)
            return skill("오류가 발생했습니다.\n요청 ID: " + req_id)

        if (end - start).days > 90:  # 90일 이상을 조회요청한 경우,
            head = ("서버 성능상의 이유로 최대 90일까지만 조회가 가능합니다."
                    "\n조회기간이 %s부터 %s까지로 제한되었습니다.\n\n" %
                    (start.date(),
                     (start + datetime.timedelta(days=90)).date()))
            end = start + datetime.timedelta(days=90)  # 종료일 앞당김
        else:
            head = "%s부터 %s까지 조회합니다.\n\n" % (start.date(), end.date())

        schdls = getData.schdl_mass(start, end, req_id, debugging)
        # 년, 월, 일, 일정 정보를 담은 튜플이 리스트로 묶여서 반환됨

        # body 쓰기, 연속되는 일정은 묶어 처리함
        for content, group in groupby(schdls, lambda k: k[3]):
            list = [*group]
            if list[0] != list[-1]:
                start_date = datetime.date(*list[0][:3])
                end_date = datetime.date(*list[-1][:3])
                body = '%s%s(%s)~%s(%s):\n%s\n' % (body, start_date,
                                                   wday(start_date), end_date,
                                                   wday(end_date), content)
            else:
                date = datetime.date(*list[0][:3])
                body = '%s%s(%s):\n%s\n' % (body, date, wday(date), content)

        if not body:
            body = "일정이 없습니다.\n"
        msg = (head + body)[:-1]  # 맨 끝의 줄바꿈을 제거함
        # 기간 조회 끝

    else:  # 아무런 파라미터도 넘겨받지 못한 경우
        log.info("[#%s] cal@modules/skill.py: No Parameter" % req_id)
        return skill("오늘, 이번 달 등의 날짜 또는 기간을 입력해 주세요.")

    return skill(msg)
Ejemplo n.º 20
0
def wtemp(req_id, debugging):
    log.info("[#%s] wtemp@modules/getData.py: Started Fetching Water Temperature Data" % req_id)
    global date, temp

    def parse():
        log.info("[#%s] wtemp@modules/getData.py: Started Parsing Water Temperature Data" % req_id)
        try:
            global date, temp
            parser = WTempParser.get(req_id, debugging)
            date = parser[0]
            temp = parser[1]
        except Exception:
            log.err("[#%s] wtemp@modules/getData.py: Failed to Fetch Water Temperature Data" % req_id)
            return "측정소 또는 서버 오류입니다."
        if not temp.isalpha():  # 무효값 걸러냄(값이 유효할 경우에만 캐싱)
            with open('data/cache/wtemp.json', 'w',
                      encoding="utf-8") as make_file:  # 캐시 만들기
                json.dump({"timestamp": int(date.timestamp()), "temp": temp}, make_file, ensure_ascii=False, indent="\t")
                print("File Created")
                temp = temp + "°C"
        log.info("[#%s] wtemp@modules/getData.py: Succeeded" % req_id)

    if os.path.isfile('data/cache/wtemp.json'):  # 캐시 있으면
        try:
            log.info("[#%s] wtemp@modules/getData.py: Read Data in Cache" % req_id)
            with open('data/cache/wtemp.json', encoding="utf-8") as data_file:  # 캐시 읽기
                data = json.load(data_file, object_pairs_hook=OrderedDict)
        except Exception:  # 캐시 읽을 수 없으면
            try:
                os.remove('data/cache/wtemp.json')  # 캐시 삭제
            except Exception:
                log.err("[#%s] wtemp@modules/getData.py: Failed to Delete Cache" % req_id)
                return "측정소 또는 서버 오류입니다."
            parser_response = parse()  # 파싱
        # 캐시 유효하면
        if (datetime.datetime.now() - datetime.datetime.fromtimestamp(data["timestamp"])
                < datetime.timedelta(minutes=76)):  # 실시간수질정보시스템상 자료처리 시간 고려, 유효기간 76분으로 설정
            log.info("[#%s] wtemp@modules/getData.py: Use Data in Cache" % req_id)
            date = datetime.datetime.fromtimestamp(data["timestamp"])
            temp = data["temp"] + "°C"
            parser_response = None
        else:  # 캐시 무효하면
            log.info("[#%s] wtemp@modules/getData.py: Cache Expired" % req_id)
            parser_response = parse()  # 파싱
    else:  # 캐시 없으면
        log.info("[#%s] temp@modules/getData.py: No Cache" % req_id)
        parser_response = parse()  # 파싱

    if parser_response == "측정소 또는 서버 오류입니다.":
        return "측정소 또는 서버 오류입니다."
    time = date.hour
    # 24시간제 -> 12시간제 변환
    if time == 0 or time == 24:  # 자정
        time = "오전 12시"
    elif time < 12:  # 오전
        time = "오전 %s시" % time
    elif time == 12:  # 정오
        time = "오후 12시"
    else:  # 오후
        time = "오후 %s시" % (time - 12)

    body = "%s %s 측정자료:\n한강 수온은 %s 입니다." % (date.date(), time, temp)
    log.info("[#%s] wtemp@modules/getData.py: Succeeded" % req_id)

    return body
Ejemplo n.º 21
0
def parse(summoner_name, req_id, debugging):
    global api_key
    log.info("[#%s] parse@modules/LoL.py: Started" % req_id)

    if debugging:
        if not summoner_name:
            summoner_name = summoner_name_for_debug
        api_key = api_key_for_debug

    header = {'X-Riot-Token': api_key}

    # 소환사 정보 가져오기
    try:
        summoner_req = urllib.request.Request(
            api_baseurl + 'lol/summoner/v4/summoners/by-name/' +
            urllib.parse.quote(summoner_name),
            data=None,
            headers=header)

        summoner_data = json.load(urllib.request.urlopen(summoner_req))
        summoner_id = summoner_data["id"]
        account_id = summoner_data["accountId"]
    except Exception as error:
        if "404" in str(error):
            return None
        if "401" in str(error) or "403" in str(error):
            return "Invalid Token"
        if debugging:
            print(error)
        log.err("[#%s] parse@modules/LoL.py: Failed to Parse Summoner Data" %
                req_id)
        return error

    # 소환사의 리그정보 가져오기
    try:
        league_req = urllib.request.Request(
            api_baseurl + 'lol/league/v4/entries/by-summoner/' + summoner_id,
            data=None,
            headers=header)

        league_data = json.load(urllib.request.urlopen(league_req))
    except Exception as error:
        if debugging:
            print(error)
        log.err("[#%s] parse@modules/LoL.py: Failed to Parse League Data" %
                req_id)
        return error

    # 소환사의 경기전적 가져오기
    try:
        match_req = urllib.request.Request(
            api_baseurl + 'lol/match/v4/matchlists/by-account/' + account_id +
            '?endIndex=20',
            data=None,
            headers=header)

        match_data = json.load(urllib.request.urlopen(match_req))
    except Exception as error:
        if "404" in str(error):
            match_data = None
        else:
            if debugging:
                print(error)
            log.err("[#%s] parse@modules/LoL.py: Failed to Parse Match Data" %
                    req_id)
            return error

    # 소환사 정보 딕셔너리로 만들기
    data = dict()
    data["summoner"] = {
        "name":
        summoner_data["name"],  # 소환사명
        "level":
        summoner_data["summonerLevel"],  # 소환사 레벨
        "profileIcon":
        ("https://ddragon.leagueoflegends.com/cdn/9.24.2/img/profileicon/%s.png"
         % summoner_data["profileIconId"]),  # 프로필 아이콘
        "OPGG":
        "https://www.op.gg/summoner/userName="******"ranked_solo"] = None
    data["ranked_flex"] = None
    for league in league_data:
        # 솔랭 전적
        if league["queueType"] == "RANKED_SOLO_5x5":
            data["ranked_solo"] = {
                "wins":
                league["wins"],
                "losses":
                league["losses"],
                "winningRate":
                calculate_winning_late(league["wins"], league["losses"]),
                "rank":
                league["rank"],
                "tier":
                league["tier"],
                "leaguePoints":
                league["leaguePoints"]
            }
        # 자유랭 전적
        elif league["queueType"] == "RANKED_FLEX_SR":
            data["ranked_flex"] = {
                "wins":
                league["wins"],
                "losses":
                league["losses"],
                "winningRate":
                calculate_winning_late(league["wins"], league["losses"]),
                "rank":
                league["rank"],
                "tier":
                league["tier"],
                "leaguePoints":
                league["leaguePoints"]
            }
        else:
            continue

    if match_data:
        data["games"] = match_data["endIndex"]  # 선호도 계산에 사용된 게임 판수(최대 20판)
        lane = list()
        champion = list()
        # 레인과 챔피언으로 List 만들기
        for i in match_data["matches"]:
            if not i["lane"] == "NONE":
                lane.append(i["lane"])
            champion.append(i["champion"])

        # 챔피언 정보 가져오고 ID와 한국어 이름으로 딕셔너리 만들기
        champion_names = dict()
        try:
            if os.path.isfile('data/champion.json'):
                with open('data/champion.json',
                          encoding="utf-8") as data_file:  # 캐시 읽기
                    champion_data = json.load(data_file)["data"]
            else:  # 캐시 없으면
                if os.path.isfile('../data/champion.json'):
                    with open('../data/champion.json',
                              encoding="utf-8") as data_file:  # 캐시 읽기
                        champion_data = json.load(data_file)["data"]
        except Exception as error:
            if debugging:
                print(error)
            log.err(
                "[#%s] parse@modules/LoL.py: Failed to Parse Champion Data" %
                req_id)
            return error
        for i in champion_data:
            champion_names[int(
                champion_data[i]["key"])] = champion_data[i]["name"]

        # 선호레인과 챔피언 구하고 플레이 비율 구하기
        data["preferredLane"] = Counter(lane).most_common(1)[0][0], int(
            Counter(lane).most_common(1)[0][1] / data["games"] * 100)
        preferred_champion = Counter(champion).most_common(1)[0]
        data["preferredChampion"] = champion_names[preferred_champion[0]], int(
            preferred_champion[1] / data["games"] * 100)
    else:
        data["games"] = 0
        data["preferredLane"] = None
        data["preferredChampion"] = None

    log.info("[#%s] parse@modules/LoL.py: Succeeded" % req_id)

    return data
Ejemplo n.º 22
0
def publish(fb_token, req_id, debugging):

    fb = "OK"
    status = 200

    tomorrow = datetime.now() + timedelta(days=1)  # 내일
    meal = getData.meal(str(tomorrow.year), str(tomorrow.month),
                        str(tomorrow.day), req_id, debugging)  # 급식정보 불러오기

    log.info("[#%s] publish@modules/FB.py: Started Publishing" % req_id)

    # 급식데이터가 있는지 확인
    if "message" in meal:
        if meal["message"] == "등록된 데이터가 없습니다.":
            if debugging:
                print("NoData")
            log.info("[#%s] publish@modules/FB.py: No Data" % req_id)
            return {"Parser": "NoData"}, 200
        else:
            if debugging:
                print("NoData")
            log.err("[#%s] publish@modules/FB.py: Failed to Publish" % req_id)
            return {"Parser": "ERROR"}, 500
    else:
        date = meal["date"]  # 날짜 - YYYY-MM-DD(Weekday)
        menu = re.sub(r'\[[^\]]*\]', '',
                      meal["menu"]).split('\n')  # 괄호(알레르기정보) 제거, 행별로 나누기
        kcal = meal["kcal"] + " kcal"  # 열량값에 단위(kcal)붙이기

    # 템플릿
    try:
        tmpl = Image.open('data/FB_Template.png')
        pmap_tmpl = tmpl.load()
    except FileNotFoundError:
        log.err("[#%s] publish@modules/FB.py: Failed" % req_id)
        return {"Parser": "OK", "IMG": "Missing File"}, 500
    except Exception:
        log.err("[#%s] publish@modules/FB.py: Failed" % req_id)
        return {"Parser": "OK", "IMG": "FAIL"}, 500

    # 이미지 생성
    output = Image.new(tmpl.mode, tmpl.size)
    pmap_output = output.load()

    # 템플릿의 Pixel Map을 복제
    for x in range(output.size[0]):
        for y in range(output.size[1]):
            pmap_output[x, y] = pmap_tmpl[x, y]

    # 글꼴과 크기 정의
    font_date = ImageFont.truetype('data/NotoSansCJKkr-Bold.otf', 72)
    font_menu = ImageFont.truetype('data/NotoSansCJKkr-Bold.otf', 64)
    font_kcal = ImageFont.truetype('data/NotoSansCJKkr-Bold.otf', 56)

    # 날짜 그리기
    ImageDraw.Draw(output).text((84, 62), date, (59, 111, 217), font=font_date)

    # 메뉴 그리기
    for i in range(len(menu)):
        # 별이 있는 경우(맛있는 메뉴) 파란색으로 강조하기
        if '⭐' in menu[i]:
            ImageDraw.Draw(output).text((84, 204 + (77 * i)),
                                        menu[i].replace('⭐', ''),
                                        (59, 111, 217),
                                        font=font_menu)
        else:
            ImageDraw.Draw(output).text((84, 204 + (77 * i)),
                                        menu[i], (0, 0, 0),
                                        font=font_menu)

    # 열량 그리기
    ImageDraw.Draw(output).text((219, 923),
                                kcal, (59, 111, 217),
                                font=font_kcal)

    # RAM에 임시로 파일 저장
    temp = io.BytesIO()
    output.save(temp, format="png")

    # Facebook에 업로드
    if fb_token:
        try:
            graph = facebook.GraphAPI(access_token=fb_token)
            graph.put_photo(image=temp.getvalue(),
                            message=date + " 급식")  # YYYY-MM-DD(Weekday) 급식
        except facebook.GraphAPIError as error:
            if debugging:
                print(error)
            if str(error) == "Invalid OAuth access token.":
                fb = "Invalid Token"
                status = 400
            else:
                fb = "ERR"
                status = 500
        except Exception:
            fb = "ERR"
            status = 500
    else:
        fb = "No Token"

    # OK 반환
    log.info("[#%s] publish@modules/FB.py: Succeeded" % req_id)
    return {"Parser": "OK", "IMG": "OK", "fb": fb}, status
Ejemplo n.º 23
0
def parse(req_id, debugging):

    log.info("[#%s] parse@modules/weatherParser.py: Started Parsing Weather" %
             req_id)

    try:
        url = urllib.request.urlopen(
            "https://www.kma.go.kr/wid/queryDFSRSS.jsp"
            "?zone=%s" % region)
    except Exception as error:
        if debugging:
            print(error)
        log.err("[#%s] parse@modules/weatherParser.py: Failed" % req_id)
        return error

    data = xml.etree.ElementTree.fromstring(
        url.read().decode('utf-8')).findall('.//data')

    weather = dict()
    for i in range(6):
        if data[i].find('hour').text == '9':  # 9시 찾기
            # 위치
            weather['loc'] = i
            # 시간
            weather['hour'] = data[i].find('hour').text
            # 기온/최대 기온/최소 기온
            weather['temp'] = data[i].find('temp').text
            weather['temp_max'] = data[i].find('tmx').text
            weather['temp_min'] = data[i].find('tmn').text
            # 하늘 상태 -  1: 맑음 2: 구름조금 3: 구름많음 4: 흐림
            weather['sky'] = data[i].find('sky').text
            # 강수 형태 - 0: 없음 1: 비 2: 비&눈 3: 눈
            weather['pty'] = data[i].find('pty').text
            # 강수 확률
            weather['pop'] = data[i].find('pop').text
            # 습도
            weather['reh'] = data[i].find('reh').text
            break

    if not weather:  # 날씨데이터 없을 경우(다음날 9시로 밀린 경우) 그 다음 데이터를 취함
        # 위치
        weather['loc'] = 0
        # 시간
        weather['hour'] = data[0].find('hour').text
        # 기온/최대 기온/최소 기온
        weather['temp'] = data[0].find('temp').text
        weather['temp_max'] = data[0].find('tmx').text
        weather['temp_min'] = data[0].find('tmn').text
        # 하늘 상태 -  1: 맑음 2: 구름조금 3: 구름많음 4: 흐림
        weather['sky'] = data[0].find('sky').text
        # 강수 형태 - 0: 없음 1: 비 2: 비&눈 3: 눈
        weather['pty'] = data[0].find('pty').text
        # 강수 확률
        weather['pop'] = data[0].find('pop').text
        # 습도
        weather['reh'] = data[0].find('reh').text

    weather['1st_hour'] = data[0].find('hour').text

    if weather['1st_hour'] == "24":
        weather['1st_hour'] = "0"

    # 하늘 상태, 강수 형태 대응값
    sky = ['☀ 맑음', '🌤️ 구름 조금', '🌥️ 구름 많음', '☁ 흐림']
    pty = ['❌ 없음', '🌧️ 비', '🌤️ 구름 조금', '🌥️ 구름 많음']

    # 하늘 상태 대응값 적용
    if int(weather['sky']) <= 4:
        weather['sky'] = sky[int(weather['sky']) - 1]  # 1부터 시작
    else:
        weather['sky'] = '⚠ 오류'
        log.err("[#%s] parse@modules/weatherParser.py: Failed to Parse Sky" %
                req_id)

    # 강수 형태 대응값 적용
    if int(weather['pty']) < 4:
        weather['pty'] = pty[int(weather['pty'])]
    else:
        weather['pty'] = '⚠ 오류'
        log.err(
            "[#%s] parse@modules/weatherParser.py: Failed to Parse Precipitation Type"
            % req_id)
    log.info("[#%s] parse@modules/weatherParser.py: Succeeded" % req_id)
    return weather
Ejemplo n.º 24
0
    def fetch():
        global part_code, data_1, data_2

        # 학교명으로 검색해 학교코드 알아내기
        try:
            search_req = urllib.request.Request(
                'http://comci.kr:4081/98372?92744l%s' %
                urlparse.quote(school_name.encode("EUC-KR")),
                data=None,
                headers={
                    'User-Agent':
                    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                    'Chrome/78.0.3904.70 Safari/537.36'
                })

            search_url = urllib.request.urlopen(search_req)
        except Exception as error:
            if debugging:
                print(error)
            log.err(
                "[#%s] fetch.parse@modules/TTParser.py: Failed to Parse Timetable(%s-%s, %s)"
                % (req_id, tt_grade, tt_class, tt_date))
            return error

        # 학교 검색결과 가져오기
        school_list = ast.literal_eval(
            search_url.read().decode('utf-8').replace('\x00', ''))["학교검색"]
        if debugging:
            print(school_list)

        # 검색결과를 지역으로 구분하고 학교코드 가져오기
        for i in school_list:
            if i[1] == school_region:
                part_code = i[3]
                break

        # 이번 주 시간표와 다음 주 시간표 가져오기
        try:
            fetch_req_1 = urllib.request.Request(
                'http://comci.kr:4081/98372?' +
                base64.b64encode(bytes("34739_%s_0_1" % part_code,
                                       'utf-8')).decode("utf-8"),
                data=None,
                headers={
                    'User-Agent':
                    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                    'Chrome/78.0.3904.70 Safari/537.36'
                })

            fetch_req_2 = urllib.request.Request(
                'http://comci.kr:4081/98372?' +
                base64.b64encode(bytes("34739_%s_0_2" % part_code,
                                       'utf-8')).decode("utf-8"),
                data=None,
                headers={
                    'User-Agent':
                    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                    'Chrome/78.0.3904.70 Safari/537.36'
                })

            # 시간표 디코딩
            url_1 = urllib.request.urlopen(fetch_req_1).read().decode(
                'utf-8').replace('\x00', '')
            url_2 = urllib.request.urlopen(fetch_req_2).read().decode(
                'utf-8').replace('\x00', '')
        except Exception as error:
            if debugging:
                print(error)
            log.err(
                "[#%s] fetch.parse@modules/TTParser.py: Failed to Parse Timetable(%s-%s, %s)"
                % (req_id, tt_grade, tt_class, tt_date))
            return error

        # JSON 파싱
        data_1 = json.loads(url_1)
        data_2 = json.loads(url_2)

        timestamp = int(datetime.datetime.now().timestamp())  # 타임스탬프 생성

        # 캐시 만들기
        with open('data/cache/TT.json', 'w', encoding="utf-8") as make_file:
            json_cache = dict()
            json_cache["1"] = dict()
            json_cache["2"] = dict()
            json_cache["Timestamp"] = timestamp
            # 필요한 자료들만 선별에서 캐싱하기
            json_cache["1"]["자료14"] = data_1["자료14"]
            json_cache["1"]["자료81"] = data_1["자료81"]
            json_cache["1"]["자료46"] = data_1["자료46"]
            json_cache["1"]["자료92"] = data_1["자료92"]
            json_cache["2"]["자료14"] = data_2["자료14"]
            json_cache["2"]["자료81"] = data_2["자료81"]
            json_cache["2"]["자료46"] = data_2["자료46"]
            json_cache["2"]["자료92"] = data_2["자료92"]
            json_cache["2"]["시작일"] = data_2["시작일"]
            json.dump(json_cache, make_file, ensure_ascii=False, indent="\t")
            print("File Created")
Ejemplo n.º 25
0
def parse(tt_grade, tt_class, year, month, date, req_id, debugging):
    global sunday, data_1, data_2
    part_code = str()
    tt_date = datetime.date(year, month, date)
    tt_grade = int(tt_grade)
    tt_class = int(tt_class)

    log.info(
        "[#%s] parse@modules/TTParser.py: Started Parsing Timetable(%s-%s, %s)"
        % (req_id, tt_grade, tt_class, tt_date))

    # 데이터 가져오기
    def fetch():
        global part_code, data_1, data_2

        # 학교명으로 검색해 학교코드 알아내기
        try:
            search_req = urllib.request.Request(
                'http://comci.kr:4081/98372?92744l%s' %
                urlparse.quote(school_name.encode("EUC-KR")),
                data=None,
                headers={
                    'User-Agent':
                    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                    'Chrome/78.0.3904.70 Safari/537.36'
                })

            search_url = urllib.request.urlopen(search_req)
        except Exception as error:
            if debugging:
                print(error)
            log.err(
                "[#%s] fetch.parse@modules/TTParser.py: Failed to Parse Timetable(%s-%s, %s)"
                % (req_id, tt_grade, tt_class, tt_date))
            return error

        # 학교 검색결과 가져오기
        school_list = ast.literal_eval(
            search_url.read().decode('utf-8').replace('\x00', ''))["학교검색"]
        if debugging:
            print(school_list)

        # 검색결과를 지역으로 구분하고 학교코드 가져오기
        for i in school_list:
            if i[1] == school_region:
                part_code = i[3]
                break

        # 이번 주 시간표와 다음 주 시간표 가져오기
        try:
            fetch_req_1 = urllib.request.Request(
                'http://comci.kr:4081/98372?' +
                base64.b64encode(bytes("34739_%s_0_1" % part_code,
                                       'utf-8')).decode("utf-8"),
                data=None,
                headers={
                    'User-Agent':
                    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                    'Chrome/78.0.3904.70 Safari/537.36'
                })

            fetch_req_2 = urllib.request.Request(
                'http://comci.kr:4081/98372?' +
                base64.b64encode(bytes("34739_%s_0_2" % part_code,
                                       'utf-8')).decode("utf-8"),
                data=None,
                headers={
                    'User-Agent':
                    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                    'Chrome/78.0.3904.70 Safari/537.36'
                })

            # 시간표 디코딩
            url_1 = urllib.request.urlopen(fetch_req_1).read().decode(
                'utf-8').replace('\x00', '')
            url_2 = urllib.request.urlopen(fetch_req_2).read().decode(
                'utf-8').replace('\x00', '')
        except Exception as error:
            if debugging:
                print(error)
            log.err(
                "[#%s] fetch.parse@modules/TTParser.py: Failed to Parse Timetable(%s-%s, %s)"
                % (req_id, tt_grade, tt_class, tt_date))
            return error

        # JSON 파싱
        data_1 = json.loads(url_1)
        data_2 = json.loads(url_2)

        timestamp = int(datetime.datetime.now().timestamp())  # 타임스탬프 생성

        # 캐시 만들기
        with open('data/cache/TT.json', 'w', encoding="utf-8") as make_file:
            json_cache = dict()
            json_cache["1"] = dict()
            json_cache["2"] = dict()
            json_cache["Timestamp"] = timestamp
            # 필요한 자료들만 선별에서 캐싱하기
            json_cache["1"]["자료14"] = data_1["자료14"]
            json_cache["1"]["자료81"] = data_1["자료81"]
            json_cache["1"]["자료46"] = data_1["자료46"]
            json_cache["1"]["자료92"] = data_1["자료92"]
            json_cache["2"]["자료14"] = data_2["자료14"]
            json_cache["2"]["자료81"] = data_2["자료81"]
            json_cache["2"]["자료46"] = data_2["자료46"]
            json_cache["2"]["자료92"] = data_2["자료92"]
            json_cache["2"]["시작일"] = data_2["시작일"]
            json.dump(json_cache, make_file, ensure_ascii=False, indent="\t")
            print("File Created")

    if os.path.isfile('data/cache/TT.json'):  # 캐시 있으면
        try:
            log.info("[#%s] parse@modules/TTParser.py: Read Data in Cache" %
                     req_id)
            with open('data/cache/TT.json',
                      encoding="utf-8") as data_file:  # 캐시 읽기
                global data_1, data_2
                data = json.load(data_file)
                data_1 = data["1"]
                data_2 = data["2"]
        except Exception:  # 캐시 읽을 수 없으면
            try:
                # 캐시 삭제
                os.remove('data/cache/TT.json')
            except Exception as error:
                log.err(
                    "[#%s] parse@modules/TTParser.py: Failed to Delete Cache" %
                    req_id)
                return error
            fetch()  # 파싱
        # 캐시 유효하면
        if datetime.datetime.now() - datetime.datetime.fromtimestamp(
                data["Timestamp"]) < datetime.timedelta(hours=3):
            log.info("[#%s] parse@modules/TTParser.py: Use Data in Cache" %
                     req_id)
        else:  # 캐시 무효하면
            log.info("[#%s] parse@modules/TTParser.py: Cache Expired" % req_id)
            fetch()  # 파싱
    else:  # 캐시 없으면
        log.info("[#%s] parse@modules/TTParser.py: No Cache" % req_id)
        fetch()  # 파싱

    # 날짜비교 기준일(2번째 자료의 시작일) 파싱
    data_2_date = data_2["시작일"].split("-")
    data_2_date = datetime.date(int(data_2_date[0]), int(data_2_date[1]),
                                int(data_2_date[2]))

    # 기준일이 조회일보다 미래이고, 날짜차이가 7일 이내일 때, 첫 번째 자료 선택
    if data_2_date >= tt_date and (data_2_date - tt_date).days <= 7:
        data = data_1
    # 조회일이 기준일보다 미래이고, 날짜차이가 6일 이내일 때, 두 번째 자료 선택
    elif data_2_date <= tt_date and (tt_date - data_2_date).days <= 6:
        data = data_2
    else:
        return None

    tt = data["자료14"][tt_grade][tt_class]  # 자료14에 각 반의 일일시간표 정보가 담겨있음
    og_tt = data["자료81"][tt_grade][tt_class]  # 자료81에 각 반의 원본시간표 정보가 담겨있음
    teacher_list = data["자료46"]  # 교사명단
    subject_list = data["자료92"]  # 2글자로 축약한 과목명단 - 전체 명칭은 긴자료92에 담겨있음

    # 파이썬의 weekday는 월요일부터 시작하지만
    # 컴시간의 weekday는 일요일부터 시작한다
    # 파이썬 → 컴시간 형식변환
    if tt_date.weekday() == 6:
        comci_weekday = 0
    else:
        comci_weekday = tt_date.weekday() + 1

    if debugging:
        print(tt[comci_weekday])

    return_data = list()
    for i in range(len(tt[comci_weekday])):
        if tt[comci_weekday][i] != 0:
            subject = subject_list[int(str(
                tt[comci_weekday][i])[-2:])]  # 뒤의 2자리는 과목명을 나타냄
            teacher = teacher_list[int(str(
                tt[comci_weekday][i])[:-2])]  # 나머지 숫자는 교사명을 나타냄
            if not tt[comci_weekday][i] == og_tt[comci_weekday][i]:
                return_data.append("⭐%s(%s)" %
                                   (subject, teacher))  # 시간표 변경사항 표시
            else:
                return_data.append("%s(%s)" % (subject, teacher))

    # 리스트에서 0 제거
    tt[comci_weekday] = [i for i in tt[comci_weekday] if i != 0]
    og_tt[comci_weekday] = [i for i in og_tt[comci_weekday] if i != 0]

    # 단축수업, 연장수업, 시간표없음 표시
    if tt[comci_weekday] and og_tt[comci_weekday]:
        # 교시수 구하기
        tt_num = len(tt[comci_weekday])
        og_tt_num = len(og_tt[comci_weekday])

        if tt_num == og_tt_num:
            pass
        elif tt_num < og_tt_num:
            return_data.append("[MSG]⭐단축수업이 있습니다. (%s교시 → %s교시)" %
                               (og_tt_num, tt_num))
        elif tt_num > og_tt_num:
            return_data.append("[MSG]⭐연장수업이 있습니다. (%s교시 → %s교시)" %
                               (og_tt_num, tt_num))

        log.info("[#%s] parse@modules/TTParser.py: Succeeded(%s-%s, %s)" %
                 (req_id, tt_grade, tt_class, tt_date))
    else:
        return_data.append("[MSG]⭐수업을 실시하지 않습니다. (시간표 없음)")

    return return_data
Ejemplo n.º 26
0
def lol(reqdata, req_id, debugging):
    log.info("[#%s] lol@modules/skill.py: New Request" % req_id)
    try:
        summoner_name = json.loads(reqdata)["action"]["params"]["summonerName"]
    except Exception:
        log.err(
            "[#%s] lol@modules/skill.py: Error while Parsing Summoner Name" %
            req_id)
        return skill("오류가 발생했습니다.\n요청 ID: " + req_id)

    # 소환사명 16자 초과하면
    if len(summoner_name) > 16:
        log.info("[#%s] lol@modules/skill.py: Summoner Name is Too Long" %
                 req_id)
        return {
            'version': '2.0',
            'template': {
                'outputs': [{
                    "basicCard": {
                        "title":
                        "소환사명이 너무 김",
                        "description":
                        "소환사명이 너무 깁니다.\n"
                        "소환사명은 영문 16자, 한글 8자 이내입니다.\n"
                        "잘못 입력하진 않았는지 확인해주세요.",
                        "buttons": [{
                            "action": "message",
                            "label": "다시 검색하기",
                            "messageText": "롤 전적 조회하기"
                        }]
                    }
                }]
            }
        }

    try:
        summoner_data = LoL.parse(summoner_name, req_id, debugging)
    except Exception:
        log.err(
            "[#%s] lol@modules/skill.py: Error while Parsing Summoner Data" %
            req_id)
        return skill_simpletext("오류가 발생했습니다.\n요청 ID: " + req_id)

    if summoner_data == 'Invalid Token':
        log.err("[#%s] lol@modules/skill.py: Invalid Token" % req_id)
        return skill_simpletext("오류가 발생했습니다.\n요청 ID: " + req_id)
    elif summoner_data:
        # 솔랭 전적 구하기
        if summoner_data["ranked_solo"]:
            solo = ("솔랭 전적:\n"
                    "%s %s (%s LP)\n"
                    "%s승 %s패 (%s%%)\n\n" %
                    (summoner_data["ranked_solo"]["tier"],
                     summoner_data["ranked_solo"]["rank"],
                     summoner_data["ranked_solo"]["leaguePoints"],
                     summoner_data["ranked_solo"]["wins"],
                     summoner_data["ranked_solo"]["losses"],
                     summoner_data["ranked_solo"]["winningRate"]))
        else:
            solo = "솔랭 전적이 없습니다. 분발하세요!\n\n"

        # 자유랭 전적 구하기
        if summoner_data["ranked_flex"]:
            flex = ("자유랭 전적:\n"
                    "%s %s (%s LP)\n"
                    "%s승 %s패 (%s%%)\n\n" %
                    (summoner_data["ranked_flex"]["tier"],
                     summoner_data["ranked_flex"]["rank"],
                     summoner_data["ranked_flex"]["leaguePoints"],
                     summoner_data["ranked_flex"]["wins"],
                     summoner_data["ranked_flex"]["losses"],
                     summoner_data["ranked_flex"]["winningRate"]))
        else:
            flex = "자유랭 전적이 없습니다. 분발하세요!\n\n"

        # 통계 내기
        if summoner_data["games"]:
            if summoner_data["preferredLane"]:
                preferred_lane = "%s(%s%%)" % (
                    summoner_data["preferredLane"][0],
                    summoner_data["preferredLane"][1])
            else:
                preferred_lane = "정보없음"
            if summoner_data["preferredChampion"]:
                preferred_champion = ("%s(%s%%)" %
                                      (summoner_data["preferredChampion"][0],
                                       summoner_data["preferredChampion"][1]))
            else:
                preferred_champion = "정보없음"
            preferences = ("최근 %s번의 매치를 바탕으로 분석한 결과입니다:\n"
                           "많이한 라인: %s\n"
                           "많이한 챔피언: %s") % (summoner_data["games"],
                                             preferred_lane,
                                             preferred_champion)
        else:
            preferences = "통계가 없습니다. 분발하세요!"

        return {
            'version': '2.0',
            'template': {
                'outputs': [{
                    "basicCard": {
                        "title":
                        "%s (레벨 %s)" % (summoner_data["summoner"]["name"],
                                        summoner_data["summoner"]["level"]),
                        "description":
                        solo + flex + preferences,
                        "thumbnail": {
                            "imageUrl":
                            summoner_data["summoner"]["profileIcon"]
                        },
                        "buttons": [{
                            "action":
                            "webLink",
                            "label":
                            "OP.GG에서 보기",
                            "webLinkUrl":
                            summoner_data["summoner"]["OPGG"]
                        }, {
                            "action": "message",
                            "label": "다른 소환사 검색하기",
                            "messageText": "롤 전적 조회하기"
                        }]
                    }
                }]
            }
        }
    else:
        return {
            'version': '2.0',
            'template': {
                'outputs': [{
                    "basicCard": {
                        "title":
                        "소환사를 찾을 수 없음",
                        "description":
                        summoner_name + " 소환사를 찾을 수 없습니다.\n"
                        "한국 서버에 등록된 소환사가 맞는지, "
                        "잘못 입력하진 않았는지 확인해주세요.",
                        "buttons": [{
                            "action": "message",
                            "label": "다시 검색하기",
                            "messageText": "롤 전적 조회하기"
                        }]
                    }
                }]
            }
        }