Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature/deploy2 또다른 deploy 방법 #23

Closed
wants to merge 68 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
ca5029c
Sync with main (#10)
Seokyoung-Hong Mar 25, 2024
c9d991c
Add files via upload
IvyKi Mar 27, 2024
a46bdaa
Crawler 폴더 이동
Seokyoung-Hong Mar 27, 2024
a29fc57
📰feat: 텍스트 카드 함수 생성
Seokyoung-Hong Mar 27, 2024
053126c
📦feat: Update __init__.py
Seokyoung-Hong Mar 27, 2024
bdfd58d
✨feat: 학식 발화 API 추가
Seokyoung-Hong Mar 27, 2024
d449a4f
🙈chore: .gitignore 수정
Seokyoung-Hong Mar 27, 2024
faa7fe5
🔨refactor: make_textcard 함수명 변경
Seokyoung-Hong Mar 27, 2024
d2d9bbb
♻️ refactor: utils 임포트 상대경로로 수정
Seokyoung-Hong Mar 27, 2024
2b61167
♻️ refactor: Type Hinting for Mypy
Seokyoung-Hong Mar 27, 2024
1749732
:recycle: refactor: get_meals() 함수 변경
IvyKi Mar 30, 2024
2f40cac
chore: cralwer file 위치 변경
IvyKi Apr 1, 2024
c9149ad
Delete crawler directory
IvyKi Apr 1, 2024
6905ea0
chore: app.py 버전 수정
IvyKi Apr 1, 2024
c87ba0f
Update: kako-library
Seokyoung-Hong May 14, 2024
5a1f46f
delete: 코드리뷰와 Merge를 위한 불필요 코드 제거
Seokyoung-Hong May 14, 2024
491349c
Feature/cafeteria 1 view (#20)
Seokyoung-Hong May 22, 2024
cd2df2f
Feature/cafeteria 1 registration (#19)
Seokyoung-Hong May 22, 2024
beb9464
fix: 병합 실수 해결
Seokyoung-Hong May 22, 2024
c37f4c9
fix: 병합실수 해결 crawler/settings.py
Seokyoung-Hong May 22, 2024
7c90645
fix: handle_errors 함수 오류 수정
Seokyoung-Hong May 22, 2024
ed47e1d
chore: 도움말 quickReply 제거
Seokyoung-Hong May 22, 2024
ee2ecac
update: view 함수 수정
Seokyoung-Hong May 22, 2024
5390b78
fix: opening_time 인스턴스 -> datetime 객체 형태로 출력 수정
IvyKi May 25, 2024
d13e4ed
feature: registration.py, view.py 합치기
IvyKi May 25, 2024
98d1b7c
fix: registration_time 시간정보 추출 point 변경
IvyKi May 25, 2024
0ef28b4
Delete sandol/crawler/cafeteria_registration.py
IvyKi May 25, 2024
c63e2dd
Delete sandol/crawler/cafeteria_view.py
IvyKi May 25, 2024
e0288df
Delete sandol/crawler/restaurant.py
IvyKi May 25, 2024
0e0be62
fix: registration_time 지정 시 datetime 객체로 지정
IvyKi May 25, 2024
c5e7477
fix: by_dict() classmethod 생성 -> get_meals() 함수 수정
IvyKi May 25, 2024
4ee8b26
update: crawler의 각종 기능 지원을 위한 requirements.txt 수정
Seokyoung-Hong May 26, 2024
d6e4d67
update: kakao 라이브러리 업데이트
Seokyoung-Hong May 26, 2024
f1c1837
feat: utils.py 각종 기능 추가 및 make_meal_card 관련 함수 수정
Seokyoung-Hong May 26, 2024
f4a251b
feat: api_server/settings.py 식단 등록 반환용 quick_reply 이관
Seokyoung-Hong May 26, 2024
257b255
feat: utils.py meal_error_response_maker 함수 추가
Seokyoung-Hong May 26, 2024
1639720
refactor: 불필요 코드 삭제
Seokyoung-Hong May 26, 2024
78b2017
feat: 등록 검증 API 추가와 에러 처리 및 검증 관련 각종 코드 수정
Seokyoung-Hong May 26, 2024
64e34cb
chore: menu 개수 제한 코드 주석처리
Seokyoung-Hong May 26, 2024
20f3e3b
refactor: module 호출 부분 line to long 해결
Seokyoung-Hong May 26, 2024
6d8ad84
Merge branch 'main' into feature/cafeteria-1
Seokyoung-Hong May 27, 2024
acfa09c
refactor: rename bookDownloader to ibookdownloader and add module doc…
Seokyoung-Hong May 27, 2024
186316c
refactor: api_serer/utils.py 주석 깔끔하게
Seokyoung-Hong May 27, 2024
0cbf5c9
refactor: settings.py 등록용 퀵리플라이 목록 리스트로 전환
Seokyoung-Hong May 27, 2024
accf621
refactor: 주석을 줄였습니다.
Seokyoung-Hong May 27, 2024
f8dfd5f
updage: kakao library
Seokyoung-Hong May 29, 2024
3558747
fix: meal/view 비어있는 carousel 처리 추가
Seokyoung-Hong May 29, 2024
c26e262
fix: 식단 정보가 없을 경우에 대한 예외처리 추가
Seokyoung-Hong May 29, 2024
df30eec
update: fastAPI로 프레임워크 마이그레이션
Seokyoung-Hong May 29, 2024
fe088b5
chore: 불필요한 내용 제거
Seokyoung-Hong May 29, 2024
4b10756
delete: 불필요 파일 삭제
Seokyoung-Hong May 29, 2024
968e200
refactor: meal module 구조
Seokyoung-Hong May 29, 2024
4057091
refactor: utils.py/meal_response_maker 코드 간소화
Seokyoung-Hong May 30, 2024
f07f51f
refactor: 모듈 import 절대 경로 사용
Seokyoung-Hong May 30, 2024
1f5f176
refactor: 불필요 코드 삭제
Seokyoung-Hong May 30, 2024
f8f8e7d
refactor: Payload와 Restaurant 객체를 반환하는 공통 함수 분리
Seokyoung-Hong May 30, 2024
666e2ea
refactor: 주석 수정
Seokyoung-Hong May 30, 2024
d3e6030
refactor: menu_list 처리를 더 간결하게 변경
Seokyoung-Hong May 30, 2024
56a510c
refactor: 주석 수정 및 코드 간소화
Seokyoung-Hong May 30, 2024
d3a67ec
fix: tip메뉴 "*복수메뉴*" 문구 필터링
IvyKi Jun 1, 2024
81cbcfc
refactor: 식당 정보를 반환하는 API 엔드포인트 추가
Seokyoung-Hong Jun 2, 2024
d0136ca
feat: mangum hanlder 적용
Seokyoung-Hong Jun 3, 2024
111f351
update: settings.py에 S3_BUCKET_NAME global 변수 추가
Seokyoung-Hong Jun 3, 2024
731d72f
add: 에러 방지용 static 파일
Seokyoung-Hong Jun 3, 2024
fb833ed
feat: s3용 boto3관련 함수 추가
Seokyoung-Hong Jun 3, 2024
7d0e39c
update: s3 적용
Seokyoung-Hong Jun 3, 2024
e5fc23f
fix: 함수 호출 우선순위 문제 해결
Seokyoung-Hong Jun 3, 2024
b927b09
feat: sam 적용
Seokyoung-Hong Jun 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,10 @@ cython_debug/
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
.idea/

### Flask template
instance/*
!instance/.gitignore
.webassets-cache
.env

.aws-sam/
5 changes: 5 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""테스트 서버를 실행시키기 위한 파일입니다."""
import uvicorn

if __name__ == "__main__":
uvicorn.run("sandol.app:app", host="0.0.0.0", port=5600, reload=True)
30 changes: 7 additions & 23 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,23 +1,7 @@
beautifulsoup4==4.12.3
blinker==1.7.0
bs4==0.0.2
certifi==2024.2.2
charset-normalizer==3.3.2
click==8.1.7
exceptiongroup==1.2.0
Flask==3.0.2
idna==3.6
importlib_metadata==7.1.0
iniconfig==2.0.0
itsdangerous==2.1.2
Jinja2==3.1.3
MarkupSafe==2.1.5
packaging==24.0
pluggy==1.4.0
pytest==8.1.1
requests==2.31.0
soupsieve==2.5
tomli==2.0.1
urllib3==2.2.1
Werkzeug==3.0.1
zipp==3.18.1
fastapi
pandas
requests
openpyxl
mangum
annotated-types
boto3
8 changes: 8 additions & 0 deletions samconfig.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
version = 0.1
[default.deploy.parameters]
stack_name = "sandol-sam"
resolve_s3 = true
s3_prefix = "sandol-sam"
region = "ap-northeast-2"
capabilities = "CAPABILITY_IAM"
image_repositories = []
10 changes: 10 additions & 0 deletions sandol/api_server/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
"""API 서버를 구성하는 모듈들

API 서버를 구성하는 모듈들이 정의되어 있습니다.
settings.py에는 환경 변수가 설정되어 있습니다.
utils.py에는 API 서버에서 사용하는 유틸리티 함수들이 정의되어 있습니다.
이외의 모듈은 각각의 API 엔드포인트를 정의하고 있습니다.
"""
from .meal import meal_api

__all__ = ["meal_api"]
11 changes: 0 additions & 11 deletions sandol/api_server/app.py

This file was deleted.

23 changes: 23 additions & 0 deletions sandol/api_server/kakao/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""카카오톡 챗봇을 개발하기 위한 라이브러리입니다.

Packages:
response: 카카오톡 응답 규칙에 맞는 응답 객체들을 정의합니다.

Modules:
base: 라이브러리의 기본 부모 클래스(BaseModel)와 스킬 템플릿(SkillTemplate)을 정의합니다.
context: 컨텍스트 정보를 담는 클래스를 정의합니다.
customerror: 사용자 정의 예외를 정의합니다.
input: 스킬 실행시 봇 시스템이 스킬 서버에게 전달하는 정보를 객체화한 Payload 객체들을 정의합니다.
utils: 라이브러리에서 사용하는 유틸리티 함수들을 정의합니다.
validation: 라이브러리에서 사용하는 유효성 검사 함수들을 정의합니다.
"""
from .base import BaseModel
from . import response
from .customerror import InvalidLinkError, InvalidTypeError, InvalidActionError
from .input import Payload, ValidationPayload

__all__ = [
"response",
"InvalidActionError", "InvalidLinkError", "InvalidTypeError",
"Payload", "ValidationPayload"
]
130 changes: 130 additions & 0 deletions sandol/api_server/kakao/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
"""카카오 라이브러리의 대부분의 클래스의 부모 클래스를 정의합니다.

classes:
BaseModel: 카카오 라이브러리의 대부분의 클래스의 부모 클래스
ParentPayload: Payload 객체의 부모 클래스
SkillTemplate: 카카오톡 스킬 응답중 SkilllTemplate을 객체로 생성하는 추상 클래스
"""
from abc import ABC, ABCMeta, abstractmethod
import json


class BaseModel(ABC, metaclass=ABCMeta):
"""카카오 라이브러리의 대부분의 클래스의 부모 클래스

카카오 라이브러리의 대부분의 클래스는 이 클래스를 상속받아 구현됩니다.
remove_none_item 메서드를 통해 None이 아닌 값만을 가진 dict를 생성할 수 있습니다.
render 메서드를 통해 객체를 카카오톡 응답 형식에 알맞게 dict로 변환하도록 구현해야 합니다.
validate 메서드를 통해 카카오톡 응답 규칙에 맞는지 검증하도록 구현해야 합니다.
"""
@staticmethod
def remove_none_item(base: dict) -> dict:
"""key-value 쌍 item을 base에서 제거합니다.

카카오톡 서버로 반환 시 None인 값을 제외하고 반환하기 위해 사용합니다.

Args:
base (dict): None인 값을 제거할 딕셔너리

Returns:
dict: None인 값을 제거한 딕셔너리
"""
out = {}
for key, value in base.items():
if value is not None:
out[key] = value
return out

@abstractmethod
def render(self) -> dict | list:
"""객체를 카카오톡 응답 형식에 알맞게 dict로 변환합니다.

변환된 dict는 각 객체가 타깃으로 하는
카카오톡 응답 형식의 상세 필드를 key로 가집니다.
TextCard 객체의 경우 다음과 같은 형식으로 변환됩니다:
{
'title': '제목',
'description': '설명',
'buttons': [
{
'action': 'webLink',
'label': '링크',
'webLinkUrl': 'https://www.example.com',
},
],
}

Returns:
dict
"""

@abstractmethod
def validate(self):
"""카카오톡 응답 규칙에 알맞은지 객체를 검증합니다.

응답 규칙에 맞지 않을 경우 예외를 발생시키도록 구현해야 합니다.
"""


class ParentPayload(ABC, metaclass=ABCMeta):
"""Payload 객체의 부모 클래스

Payload 객체들의 부모 클래스로, from_json과 from_dict 메서드를 가지고 있습니다.
Payload 객체들은 스킬 실행시 봇 시스템이 스킬 서버에게 전달하는 정보를 객체화한 것입니다.
이 객체를 상속받는 클래스 중 Payload와 Context를 제외한 클래스들은 단독으로 사용되지 않습니다.

from_dict 메서드를 통해 딕셔너리를 객체로 변환할 수 있도록 구현해야 합니다.
from_json 메서드를 통해 JSON 문자열을 객체로 변환할 수 있도록 구현해야 합니다.
"""
@classmethod
@abstractmethod
def from_dict(cls, data: dict):
"""딕셔너리를 객체로 변환하는 메서드

딕셔너리를 받아서 객체로 변환하는 메서드입니다.

Args:
data (dict): 딕셔너리
"""

@classmethod
def from_json(cls, data: str):
"""JSON 문자열을 객체로 변환하는 메서드

from_dict 메서드를 호출하여 JSON 문자열을 객체로 변환합니다.

Args:
data (str): JSON 문자열
"""
return cls.from_dict(json.loads(data))


class SkillTemplate(BaseModel, metaclass=ABCMeta):
"""카카오톡 SkillTemplate 출력요소를 객체로 생성하는 추상 클래스

BaseModel을 상속받아 구현되며, render와 validate 메서드를 구현해야 합니다.

is_empty 프로퍼티를 통해 응답 객체가 비어있는지 여부를 확인할 수 있습니다.
render() 메서드를 호출하여 생성된 응답 객체가 비어있는지 확인합니다.

Raises:
NotImplementedError: render 또는 validate 메서드가 구현되지 않았을 때

Examples:
>>> class TextCard(ParentComponent):
... name = "textCard" # 응답 객체의 템플릿 이름
>>> print(TextCard.name)
... "textCard"
"""

@property
def is_empty(self) -> bool:
"""응답 객체가 비어있는지 여부를 반환합니다.

self.render() 메서드를 호출하여 응답 객체를 생성한 후,
응답 객체가 비어있는지 여부를 반환합니다.

Returns:
bool: 응답 객체가 비어있으면 True, 아니면 False
"""
return not bool(self.render())
125 changes: 125 additions & 0 deletions sandol/api_server/kakao/context.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
"""컨텍스트 정보를 담는 클래스를 정의하는 모듈입니다.

컨텍스틑 정보는 Payload 및 Response에서 동일한 형태의 데이터로 사용되기 떄문에,
이를 통일된 형태로 관리하기 위해 별도의 모듈 및 클래스로 정의합니다.
"""

from typing import Optional
from .base import ParentPayload, SkillTemplate
from .validation import validate_int, validate_str, validate_type


class Context(ParentPayload, SkillTemplate):
"""컨텍스트 정보를 담는 클래스입니다.

컨텍스트 정보는 봇과 사용자간의 문맥적 상황 공유를 위해 사용됩니다.
컨텍스트 정보는 이름, 남은 횟수, 유지 시간, 추가 정보를 가집니다.
챗봇 관리자센터에서 컨텍스트를 설정하지 않으면 이 정보는 무시됩니다.

이 클래스는 Payload와 Response에서 사용될 수 있도록 공통된 형태로 정의됩니다.
따라서 from_dict와 render 메서드를 함께 제공합니다.

Attributes:
name (str): 컨텍스트의 이름
lifespan (int): 컨텍스트의 남은 횟수
ttl (int): 컨텍스트가 유지되는 시간
params (dict): 컨텍스트의 추가 정보

Examples:
>>> context = Context(
... name="context_name",
... lifespan=1,
... ttl=600,
... params={
... "key": "value"
... }
... )
>>> context.render()
{
"name": "context_name",
"lifespan": 1,
"ttl": 600,
"params": {
"key": "value"
}
}
"""

def __init__(
self,
name: str,
lifespan: int,
ttl: Optional[int] = None,
params: Optional[dict] = None):
"""Context 객체를 초기화합니다.

Args:
name (str): 컨텍스트의 이름
lifespan (int): 컨텍스트의 남은 횟수
ttl (int, optional): 컨텍스트가 유지되는 시간
params (dict, optional): 컨텍스트의 추가 정보
"""
super().__init__()
self.name = name
self.lifespan = lifespan
self.ttl = ttl
self.params = params

@classmethod
def from_dict(cls, data: dict) -> 'Context':
"""딕셔너리를 Context 객체로 변환합니다.

변환할 딕셔너리는 다음과 같은 형태입니다.
{
"name": "context_name",
"lifespan": 1,
"ttl": 600,
"params": {
"key": "value"
}
}

Args:
data (dict): 변환할 딕셔너리

Returns:
Context: 변환된 Context 객체
"""
return cls(**data)

def render(self) -> dict:
"""Context 객체를 카카오톡 응답 규칙에 맞게 딕셔너리로 변환합니다.

반환되는 딕셔너리는 다음과 같은 형태입니다.
{
"name": "context_name",
"lifespan": 1,
"ttl": 600,
"params": {
"key": "value"
}
}

Returns:
dict: Context 객체를 변환한 딕셔너리
"""
response = {
"name": self.name,
"lifeSpan": self.lifespan,
"ttl": self.ttl,
"params": self.params
}
return self.remove_none_item(response)

def validate(self):
"""Context 객체의 유효성을 검사합니다.

Raises:
InvalidTypeError: name이 str이 아닐 경우 발생합니다.
InvalidTypeError: lifespan이 int가 아닐 경우 발생합니다.
InvalidTypeError: ttl이 int가 아닐 경우 발생합니다.
InvalidTypeError: params가 dict가 아닐 경우 발생합니다.
"""
validate_str(self.name)
validate_int(self.lifespan, self.ttl)
validate_type(dict, self.params)
Loading