Skip to content

Commit

Permalink
Merge branch 'develop' into feature/nightmare
Browse files Browse the repository at this point in the history
  • Loading branch information
bekker committed Jan 27, 2019
2 parents 93b97dd + 51175f0 commit 061c5ea
Show file tree
Hide file tree
Showing 28 changed files with 334 additions and 143 deletions.
19 changes: 12 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@ SNU Timetable API 서버

서울대학교 수강편람 검색 및 시간표 관리를 위한 애플리케이션입니다.

## Contributing
PR is welcome!

## Framework
본 레포는 REST API 서버로서 별도의 프론트엔드 클라이언트가 필요합니다. 기기 알림과 페이스북 로그인을 지원하며, 이를 위해서는 구글 Firebase와 Facebook 프로젝트를 별도로 설정해야 합니다. MongoDB를 데이터베이스로 사용합니다.
본 프로젝트는 REST API 서버로서 별도의 프론트엔드 클라이언트가 필요합니다. 기기 알림과 페이스북 로그인을 지원하며, 이를 위해서는 구글 Firebase와 Facebook 프로젝트를 별도로 설정해야 합니다. MongoDB를 데이터베이스로 사용합니다. Redis DB를 캐시 저장소로 사용합니다.

## Requirements
* Linux (CentOS, Ubuntu, Arch, etc.)
* Node.js 4.2+ and corresponding npm
* MongoDB 2.6+
* Node.js 8.15.0
* MongoDB 3.6.9
* Redis 4.0.12

## Documentation
[깃헙 위키](https://github.com/wafflestudio/snutt/wiki/Deploying-2.0.0)
Expand All @@ -22,9 +26,10 @@ SNU Timetable API 서버
* [iOS Client](https://github.com/wafflestudio/SNUTT-iOS)

## Liability
SNUTT는 [서울대학교 수강편람 서비스](http://sugang.snu.ac.kr)에서 데이터를 다운로드 후 가공합니다. 잦은 크롤링을 수행하면, 서울대학교 측으로부터 IP 밴 등의 불이익이 있을 수 있습니다. 와플스튜디오는 데이터 크롤링에 수반하는 일체의 불이익에 대하여 책임지지 않으며 본 프로그램을 사용하는 경우 서울대학교 서비스에 부하를 가하기 않도록 유의하여야 합니다. 현재 SNUTT는 하루 한 번 데이터를 업데이트하고 있습니다.
SNUTT는 [서울대학교 수강편람 서비스](http://sugang.snu.ac.kr)에서 데이터를 다운로드 후 가공합니다. 잦은 크롤링을 수행하면, 서울대학교 측으로부터 IP 밴 등의 불이익이 있을 수 있습니다. 와플스튜디오는 데이터 크롤링에 수반하는 일체의 불이익에 대하여 책임지지 않으며, 본 프로그램을 사용하는 경우 서울대학교 서비스에 부하를 가하기 않도록 유의하여야 합니다.

## 다른 학교에서도 이용할 수 있나요?
다음과 같은 사항을 수정해야합니다.
1. `src/batch/coursebook`을 수정해서, 해당 학교의 수강편람을 받아올 수 있도록 해야 합니다. '태그' 기능이 알맞게 적용할 수 있는지 확인합니다.
2. 해당 학교의 강의 정보가 현재 강의 및 시간표 모델에 적합한지 확인해야 합니다. 적합하지 않을 때에는, `src/core/model`의 lecture, timetable, query 부분을 수정하여야 합니다.
본 프로젝트는 MIT 라이센스로 공개되어 있으므로, 열정과 시간이 있으시다면 다른 학교의 상황에 맞게 수정하실 수 있습니다.

## License
MIT
73 changes: 46 additions & 27 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "snutt",
"version": "2.1.10",
"version": "2.2.4",
"private": true,
"scripts": {
"test": "tsc -p . && cp -R resources/* build/ && mocha -r module-alias/register --exit \"build/test/**/*.js\"",
Expand Down Expand Up @@ -57,6 +57,7 @@
"request-promise-native": "~1.0.5",
"rewire": "^4.0.1",
"sinon": "^6.1.3",
"streamroller": "^0.8.5",
"supertest": "~3.1.0",
"typescript": "2.9.1",
"xlsx": "~0.13.0"
Expand Down
18 changes: 11 additions & 7 deletions snutt.yml.example
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,28 @@ core:
fcm:
apiKey: testapikey
projectId: testprojectid
feedback2github:
token: testapikey
repo:
owner: wafflestudio
name: snutt-feedbacks

api:
host: localhost
port: 3000
log4js:
path: './snutt-api.log'
pattern: '.yyyy-MM-dd'
datePattern: '.yyyy-MM-dd'
daysToKeep: 30
logLevel: debug
morgan:
path: './snutt-api-access.log'
datePattern: '.yyyy-MM-dd'
daysToKeep: 30

batch:
log4js:
path: './snutt-batch.log'
pattern: '.yyyy-MM-dd'
datePattern: '.yyyy-MM-dd'
daysToKeep: 30
logLevel: debug
feedback2github:
token: testapikey
repo:
owner: wafflestudio
name: snutt-feedbacks
20 changes: 17 additions & 3 deletions src/api/config/express.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import path = require("path");
import cors = require("cors");
import http = require('http');
import log4js = require('log4js');
import streamroller = require('streamroller');

import RootRouter = require('@app/api/routes/RootRouter');
import property = require('@app/core/config/property');
Expand All @@ -24,10 +25,24 @@ app.engine('.html', require('ejs').renderFile);
// X-Forwarded-For 헤더를 신뢰할 주소. 앞단에 nginx 프록시를 둘 경우 필요함. localhost만을 활성화한다
app.set('trust proxy', 'loopback')

let logPath = property.get("api.morgan.path");
let logDatePattern = property.get("api.morgan.datePattern");
let daysToKeep = property.get("api.morgan.daysToKeep");

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
if (app.get('env') !== 'mocha')
app.use(morgan(':remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent" :response-time ms'));
if (app.get('env') !== 'mocha') {
let morganPattern = ':remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent" :response-time ms';
let dateRollingStream = new streamroller.DateRollingFileStream(logPath, logDatePattern, {
compress: true,
alwaysIncludePattern: true,
daysToKeep: daysToKeep
});
// both stdout and file
app.use(morgan(morganPattern));
app.use(morgan(morganPattern, { stream: dateRollingStream }));
}

// Only for development
app.use(cors());
app.use(bodyParser.json());
Expand Down Expand Up @@ -56,7 +71,6 @@ if (process.env.NODE_ENV != 'mocha') {
* Create server.
*/
function createServer(): http.Server {
var protocol = "http";
var server = http.createServer(app);
server.listen(port, host, function() {
logger.info("Server listening on http://" + host + ":" + port);
Expand Down
4 changes: 2 additions & 2 deletions src/api/config/log.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import log4js = require('log4js');
import property = require('@app/core/config/property');

let logPath = property.get("api.log4js.path");
let logPattern = property.get("api.log4js.pattern");
let logDatePattern = property.get("api.log4js.datePattern");
let logLevel = property.get("api.log4js.logLevel");
let daysToKeep = property.get("api.log4js.daysToKeep");

Expand All @@ -13,7 +13,7 @@ if (process.env.NODE_ENV !== 'mocha') {
'file': {
type: 'dateFile',
filename: logPath,
pattern: logPattern,
pattern: logDatePattern,
daysToKeep: daysToKeep,
compress: true,
alwaysIncludePattern: true
Expand Down
2 changes: 1 addition & 1 deletion src/api/routes/ApiRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ restGet(router, '/app_version')(async function() {
});

restPost(router, '/feedback')(async function(context, req) {
await FeedbackService.add(req.body.email, req.body.message, req["api_platform"]);
await FeedbackService.add(req.body.email, req.body.message, context.platform);
return {message:"ok"};
});

Expand Down
5 changes: 3 additions & 2 deletions src/api/routes/NotificationRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ restGet(router, '/')(async function(context, req){
return notification;
});

restGet(router, '/count')(function(context, req){
restGet(router, '/count')(async function(context, req){
var user:User = context.user;
return NotificationService.countUnreadByUser(user);
let count = await NotificationService.countUnreadByUser(user);
return { count: count };
});

export = router;
2 changes: 1 addition & 1 deletion src/api/routes/SearchQueryRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ restPost(router, '/')(async function(context, req) {
var query: any = req.body;
try {
RefLectureQueryService.addQueryLogAsync(query);
return await RefLectureQueryService.getLectureListByQueryWithCache(query);
return await RefLectureQueryService.getLectureListByLectureQuery(query);
} catch (err) {
if (err instanceof InvalidLectureTimemaskError) {
throw new ApiError(400, ErrorCode.INVALID_TIMEMASK, "invalid timemask");
Expand Down
4 changes: 2 additions & 2 deletions src/batch/config/log.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import log4js = require('log4js');
import property = require('@app/core/config/property');

let logPath = property.get("batch.log4js.path");
let logPattern = property.get("batch.log4js.pattern");
let logDatePattern = property.get("batch.log4js.datePattern");
let logLevel = property.get("batch.log4js.logLevel");
let daysToKeep = property.get("batch.log4js.daysToKeep");

Expand All @@ -13,7 +13,7 @@ if (process.env.NODE_ENV !== 'mocha') {
'file': {
type: 'dateFile',
filename: logPath,
pattern: logPattern,
pattern: logDatePattern,
daysToKeep: daysToKeep,
compress: true,
alwaysIncludePattern: true
Expand Down
6 changes: 4 additions & 2 deletions src/batch/coursebook/data/notify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ export async function notifyUpdated(year:number, semesterIndex:number, diff:Lect
let userIdNumUpdatedMap: Map<string, number> = new Map();
let userIdNumRemovedMap: Map<string, number> = new Map();

function incrementUpdated(userId: string) {
function incrementUpdated(userId: any) {
userId = (typeof userId == 'string') ? userId : String(userId);
let oldValue = userIdNumUpdatedMap.get(userId);
if (oldValue) {
userIdNumUpdatedMap.set(userId, oldValue + 1);
Expand All @@ -24,7 +25,8 @@ export async function notifyUpdated(year:number, semesterIndex:number, diff:Lect
}
}

function incrementRemoved(userId: string) {
function incrementRemoved(userId: any) {
userId = (typeof userId == 'string') ? userId : String(userId);
let oldValue = userIdNumRemovedMap.get(userId);
if (oldValue) {
userIdNumRemovedMap.set(userId, oldValue + 1);
Expand Down
17 changes: 7 additions & 10 deletions src/batch/feedback2github/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
/**
* DB 상의 피드백을 깃헙 이슈로 전송합니다.
* $ npm run feedback2github
*
* @author Jang Ryeol, [email protected]
* Deprecated since 2.2.0
*/

require('module-alias/register');
Expand All @@ -14,17 +11,17 @@ import LambdaJobBuilder from '@app/batch/common/LambdaJobBuilder';
import FeedbackService = require('@app/core/feedback/FeedbackService');
import Feedback from '@app/core/feedback/model/Feedback';
import * as log4js from 'log4js';
import Issue from './model/Issue';
import GithubIssue from '@app/core/github/model/GithubIssue';
import property = require('@app/core/config/property');
import GithubService = require('./GithubService');
import GithubService = require('@app/core/github/GithubService');

let repoOwner = property.get('batch.feedback2github.repo.owner');
let repoName = property.get('batch.feedback2github.repo.name');
let repoOwner = property.get('core.feedback2github.repo.owner');
let repoName = property.get('core.feedback2github.repo.name');

var logger = log4js.getLogger();

interface StepItem {
issue: Issue,
issue: GithubIssue,
feedbackId: string
}

Expand Down Expand Up @@ -66,7 +63,7 @@ async function processor(feedback: Feedback): Promise<StepItem> {
labels = [feedback.platform];
}

let issue: Issue = {
let issue: GithubIssue = {
title: title,
body: body,
labels: labels
Expand Down
Loading

0 comments on commit 061c5ea

Please sign in to comment.