diff --git a/src/apis/building-info/controllers.ts b/src/apis/building-info/controllers.ts new file mode 100644 index 0000000..1ef0448 --- /dev/null +++ b/src/apis/building-info/controllers.ts @@ -0,0 +1,18 @@ +import express, { Request, Response } from 'express'; + +import fetchBuildingInfo from './service'; + +const router = express.Router(); + +router.get('/', async (req: Request, res: Response) => { + const code = req.query.code; + + try { + const buildingInfo = await fetchBuildingInfo(code as string); + res.json(buildingInfo); + } catch (err) { + console.log(err); + } +}); + +export default router; diff --git a/src/apis/building-info/service.ts b/src/apis/building-info/service.ts new file mode 100644 index 0000000..a95e4f4 --- /dev/null +++ b/src/apis/building-info/service.ts @@ -0,0 +1,99 @@ +import axios, { AxiosResponse } from 'axios'; +import notificationToSlack from 'src/hooks/notificateToSlack'; + +type Floor = 'basement' | 'ground' | 'rooftop'; + +interface Room { + roomNumber: string; + roomName: string; +} + +interface FormattedInfo extends Room { + floor: number; + floorType: Floor; +} + +type TotalInfo = { + [key in Floor]: { + [key in string]: Room[]; + }; +}; + +const configPaylod = (code: string) => { + const payload = new URLSearchParams(); + payload.append('code', code); + payload.append('stat', 'D'); + + return payload; +}; + +const handleLayerType = (layerType: string) => { + if (layerType === '0') return 'ground'; + if (layerType === '1') return 'basement'; + if (layerType === '2') return 'rooftop'; +}; + +const formatTotalInfo = (formattedInfo: FormattedInfo[]) => { + const totalInfo: TotalInfo = { + basement: {}, + ground: {}, + rooftop: {}, + }; + + formattedInfo.forEach(({ roomNumber, roomName, floor, floorType }) => { + const type = floorType as Floor; + + if (!Object.prototype.hasOwnProperty.call(totalInfo[type], floor)) { + totalInfo[type][floor] = [{ roomNumber, roomName }]; + return; + } + + totalInfo[type][floor].push({ roomNumber, roomName }); + }); + + return totalInfo; +}; + +const formatFetchedInfo = (data: AxiosResponse['data']) => { + const formattedData: FormattedInfo[] = data.response.deps2.reduce( + (accData: FormattedInfo[], curr: any) => { + const item = { + roomNumber: curr.roomNo, + roomName: curr.roomName, + floor: curr.layer, + floorType: handleLayerType(curr.layerTyp), + }; + + return [...accData, item]; + }, + [] as FormattedInfo[], + ); + + const formattedInfo = formatTotalInfo(formattedData); + + return formattedInfo; +}; + +const fetchBuildingInfo = async (code: string) => { + const REQUEST_URL = 'https://www.pknu.ac.kr/buildingInfoAjax.do'; + const HEADERS = { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36', + }; + const payload = configPaylod(code); + + try { + const response = await axios.post(REQUEST_URL, payload.toString(), { + headers: HEADERS, + }); + + const formattedInfo = formatFetchedInfo(response.data); + + return formattedInfo; + } catch (error) { + notificationToSlack('건물 정보 요청에 문제가 발생했습니다.'); + console.log(error); + } +}; + +export default fetchBuildingInfo; diff --git a/src/index.ts b/src/index.ts index 80496f8..be6c876 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,10 +1,10 @@ +import buildingInfoRouter from '@apis/building-info/controllers'; import graduationRouter from '@apis/graduation/controller'; import majorRouter from '@apis/majorDecision/controller'; import noticeRouter from '@apis/notice/controller'; import subscriptionRouter from '@apis/subscribe/controller'; import suggestionRouter from '@apis/suggestion/controller'; import env from '@config'; -import { saveMajorNoticeToDB } from '@db/data/noticeHandler'; import { corsOptions } from '@middlewares/cors'; import errorHandler from '@middlewares/error-handler'; import cors from 'cors'; @@ -30,6 +30,7 @@ app.use('/api/majorDecision', majorRouter); app.use('/api/announcement', noticeRouter); app.use('/api/graduation', graduationRouter); app.use('/api/subscription', subscriptionRouter); +app.use('/api/buildingInfo', buildingInfoRouter); app.get('/test', (req: Request, res: Response) => { console.log('test');