송용우

Merge commit '7a39581f' into feature/frontend_page

1 +jaksimsamil
2 +.vscode/
3 +*.csv
1 +# Jaksimsamil Crawler Documentation
2 +
3 +## Overview
4 +- https://acmicpc.net와 https://solved.ac에서 사용자와 문제정보를 크롤링합니다.
5 +- Python 3.8.3, Pip 20.2.1 환경에서 개발되었습니다.
6 +
7 +## Usuage
8 +
9 +- Install
10 +```bash
11 +pip install -r requirements.txt
12 +```
13 +
14 +- Run
15 +```bash
16 +python main.py
17 +```
1 +import requests
2 +from bs4 import BeautifulSoup
3 +import pandas as pd
4 +from dotenv import load_dotenv
5 +import sys
6 +import pymongo
7 +import os
8 +from datetime import datetime
9 +import json
10 +import numpy as np
11 +
12 +SAVE_EVERY=10
13 +SAVE_PATH='problems.csv'
14 +def setup():
15 + try:
16 + load_dotenv(dotenv_path='../jaksimsamil-server/.env')
17 + client=pymongo.MongoClient('/'.join(os.getenv('MONGO_URL').split('/')[:-1]))
18 + print('MongoDB Connected')
19 + return client
20 + except FileNotFoundError:
21 + print('.env is not found',file=sys.stderr)
22 + exit(1)
23 +
24 +def save(df,path='problems.csv'):
25 + print('Saving to {}...'.format(path),end='')
26 + df.to_csv(path)
27 + print('Done.')
28 +
29 +def load(path='problems.csv'):
30 + problems=pd.read_csv(path,index_col=0)
31 + return problems
32 +
33 +def get_khu_problem_list():
34 + pageNum=1
35 + idx=0
36 + problems=pd.DataFrame(columns=['problemNum','problemTitle','solvedacLevel','submitNum','correctNum','category','count'])
37 + while True:
38 + res=requests.get('https://www.acmicpc.net/school/ranklist/211/{}'.format(pageNum))
39 + status_code=res.status_code
40 + if status_code==404:
41 + break
42 + soup=BeautifulSoup(res.text,'html.parser')
43 + userlinks=soup.select('#ranklist > tbody > tr > td:nth-child(2) > a')
44 + for userlink in userlinks:
45 + href=userlink['href']
46 + res=requests.get('https://acmicpc.net'+href)
47 + print('Collecting user data...:',href.split('/')[-1])
48 + user_soup=BeautifulSoup(res.text,'html.parser')
49 + problemNums=user_soup.select('body > div.wrapper > div.container.content > div.row > div:nth-child(2) > div:nth-child(3) > div.col-md-9 > div:nth-child(1) > div.panel-body > span.problem_number')
50 + for problemNum in problemNums:
51 + if not problemNum.text in problems['problemNum'].tolist():
52 + problems=problems.append({'problemNum':problemNum.text,'count':1},ignore_index=True)
53 + else:
54 + problems.loc[problems.problemNum==problemNum.text,'count']=problems.loc[problems.problemNum==problemNum.text,'count']+1
55 + if idx%SAVE_EVERY==0:
56 + save(problems,SAVE_PATH)
57 + idx+=1
58 + pageNum+=1
59 + save(problems,SAVE_PATH)
60 + return problems
61 +
62 +def get_problem_info(problems):
63 + for idx,problemNum in enumerate(problems['problemNum'].values):
64 + res=requests.get('https://acmicpc.net/problem/{}'.format(problemNum))
65 + print('Collecting problem data...:',problemNum)
66 + soup=BeautifulSoup(res.text,'html.parser')
67 + problemTitle=soup.select('#problem_title')[0].text
68 + soup=soup.select('#problem-info > tbody > tr > td')
69 + submitNum=soup[2].text
70 + correctNum=soup[4].text
71 + problems.loc[problems.problemNum==problemNum,'problemTitle']=problemTitle
72 + problems.loc[problems.problemNum==problemNum,'submitNum']=submitNum
73 + problems.loc[problems.problemNum==problemNum,'correctNum']=correctNum
74 + if idx%SAVE_EVERY==0:
75 + save(problems,SAVE_PATH)
76 + save(problems,SAVE_PATH)
77 + return problems
78 +
79 +def get_solvedac_level(problems):
80 + for idx,problemNum in enumerate(problems['problemNum'].values):
81 + res=requests.get('https://api.solved.ac/v2/search/problems.json?query={}&page=1&sort=id&sort_direction=ascending'.format(problemNum))
82 + print('Collecting solved.ac level data...:',problemNum)
83 + result=json.loads(res.text)
84 + for problem in result['result']['problems']:
85 + if int(problem['id'])==int(problemNum):
86 + problems.loc[problems.problemNum==problemNum,'solvedacLevel']=problem['level']
87 + break
88 + if idx%SAVE_EVERY==0:
89 + save(problems,SAVE_PATH)
90 + save(problems,SAVE_PATH)
91 + return problems
92 +
93 +def get_category(problems):
94 + problems.sort_values(['problemNum'],inplace=True,ignore_index=True)
95 + problems['category']=problems['category'].fillna(json.dumps([]))
96 + pageNum=1
97 + res=requests.get('https://api.solved.ac/v2/tags/stats.json?page={}'.format(pageNum))
98 + tagsResult=json.loads(res.text)
99 + totalPages=tagsResult['result']['total_page']
100 + tags=[]
101 + tags.extend(tagsResult['result']['tags'])
102 + for pageNum in range(2,totalPages+1):
103 + res=requests.get('https://api.solved.ac/v2/tags/stats.json?page={}'.format(pageNum))
104 + tagsResult=json.loads(res.text)
105 + tags.extend(tagsResult['result']['tags'])
106 + print('total tags:',len(tags))
107 + for tag in tags:
108 + problemList=[]
109 + pageNum=1
110 + res=requests.get('https://api.solved.ac/v2/search/problems.json?query=solvable:true+tag:{}&page={}&sort=id&sort_direction=ascending'.format(tag['tag_name'],pageNum))
111 + problemResult=json.loads(res.text)
112 + totalPages=problemResult['result']['total_page']
113 + problemList.extend(problemResult['result']['problems'])
114 + for pageNum in range(2,totalPages+1):
115 + res=requests.get('https://api.solved.ac/v2/search/problems.json?query=solvable:true+tag:{}&page={}&sort=id&sort_direction=ascending'.format(tag['tag_name'],pageNum))
116 + problemResult=json.loads(res.text)
117 + problemList.extend(problemResult['result']['problems'])
118 + idx=0
119 + problemListLen=len(problemList)
120 + for problemNum in problems['problemNum'].values:
121 + if idx<problemListLen and int(problemList[idx]['id'])==int(problemNum):
122 + category=json.loads(problems.loc[problems.problemNum==problemNum,'category'].values[0])
123 + category.append(tag['full_name_ko'])
124 + problems.loc[problems.problemNum==problemNum,'category']=json.dumps(category,ensure_ascii=False)
125 + idx+=1
126 + print('Problem {} in category {}'.format(problemNum,tag['full_name_ko']))
127 + save(problems,SAVE_PATH)
128 + return problems
129 +
130 +
131 +def update_database(problems,client):
132 + database=client['jaksimsamil']
133 + collection=database['problem']
134 + dictedProblems=problems.to_dict('records')
135 + print('len of records:',len(dictedProblems))
136 + for dictedProblem in dictedProblems:
137 + dictedProblem['category']=json.loads(dictedProblem['category'])
138 + collection.update_one({'problemNum':dictedProblem['problemNum']},{'$set':dictedProblem},upsert=True)
139 +
140 +
141 +if __name__=="__main__":
142 + startTime=datetime.now()
143 + client=setup()
144 + problems=get_khu_problem_list()
145 + problems=get_problem_info(problems)
146 + problems=get_solvedac_level(problems)
147 + problems=get_category(problems)
148 + update_database(problems,client)
149 + print('Time elapsed :',(datetime.now()-startTime)/60,'mins')
150 +
1 +beautifulsoup4==4.9.1
2 +bs4==0.0.1
3 +certifi==2020.6.20
4 +chardet==3.0.4
5 +idna==2.10
6 +numpy==1.19.1
7 +pandas==1.1.0
8 +pymongo==3.11.0
9 +python-dateutil==2.8.1
10 +python-dotenv==0.14.0
11 +pytz==2020.1
12 +requests==2.24.0
13 +six==1.15.0
14 +soupsieve==2.0.1
15 +urllib3==1.25.10
...@@ -8,3 +8,4 @@ access.log ...@@ -8,3 +8,4 @@ access.log
8 8
9 # dependencies 9 # dependencies
10 /node_modules 10 /node_modules
11 +
......
...@@ -26,17 +26,18 @@ POST http://facerain.dcom.club/profile/getprofile ...@@ -26,17 +26,18 @@ POST http://facerain.dcom.club/profile/getprofile
26 26
27 ## API Table 27 ## API Table
28 28
29 -| group | description | method | URL | Detail | Auth | 29 +| group | description | method | URL | Detail | Auth |
30 -| ------- | -------------------------------------- | ------ | ----------------------- | -------------------------------------- | --------- | 30 +| --------- | -------------------------------------- | ------ | -------------------------- | -------------------------------------- | --------- |
31 -| profile | 유저가 푼 문제 조회(백준) | GET | api/profile/solvedBJ:id | [바로가기](/src/api/profile/README.md) | None | 31 +| profile | 유저가 푼 문제 조회(백준) | GET | api/profile/solvedBJ:id | [바로가기](/src/api/profile/README.md) | None |
32 -| profile | 유저가 푼 문제 동기화(백준) | PATCH | api/profile/syncBJ | [바로가기](/src/api/profile/README.md) | None | 32 +| profile | 유저가 푼 문제 동기화(백준) | PATCH | api/profile/syncBJ | [바로가기](/src/api/profile/README.md) | None |
33 -| profile | 유저 정보 수정 | POST | api/profile/setprofile | [바로가기](/src/api/profile/README.md) | JWT TOKEN | 33 +| profile | 유저 정보 수정 | POST | api/profile/setprofile | [바로가기](/src/api/profile/README.md) | JWT TOKEN |
34 -| profile | 유저 정보 받아오기 | POST | api/profile/getprofile | [바로가기](/src/api/profile/README.md) | JWT | 34 +| profile | 유저 정보 받아오기 | POST | api/profile/getprofile | [바로가기](/src/api/profile/README.md) | JWT |
35 -| profile | 추천 문제 조회 | POST | api/profile/recommend | [바로가기](/src/api/profile/README.md) | None | 35 +| profile | 추천 문제 조회 | POST | api/profile/recommend | [바로가기](/src/api/profile/README.md) | None |
36 -| profile | 친구 추가 | POST | /api/profile/addfriend | [바로가기](/src/api/profile/README.md) | JWT TOKEN | 36 +| profile | 친구 추가 | POST | /api/profile/addfriend | [바로가기](/src/api/profile/README.md) | JWT TOKEN |
37 -| notify | 슬랙 메시지 전송 요청 (목표 성취 여부) | POST | api/notify/goal | [바로가기](/src/api/notify/README.md) | Jwt Token | 37 +| notify | 슬랙 메시지 전송 요청 (목표 성취 여부) | POST | api/notify/goal | [바로가기](/src/api/notify/README.md) | Jwt Token |
38 -| notify | 슬랙 메시지 전송 요청 (문제 추천) | POST | api/notify/recommend | [바로가기](/src/api/notify/README.md) | None | 38 +| notify | 슬랙 메시지 전송 요청 (문제 추천) | POST | api/notify/recommend | [바로가기](/src/api/notify/README.md) | None |
39 -| auth | 로그인 | POST | api/auth/login | [바로가기](/src/api/auth/README.md) | None | 39 +| auth | 로그인 | POST | api/auth/login | [바로가기](/src/api/auth/README.md) | None |
40 -| auth | 로그아웃 | POST | api/auth/logout | [바로가기](/src/api/auth/README.md) | JWT Token | 40 +| auth | 로그아웃 | POST | api/auth/logout | [바로가기](/src/api/auth/README.md) | JWT Token |
41 -| auth | 회원가입 | POST | api/auth/register | [바로가기](/src/api/auth/README.md) | None | 41 +| auth | 회원가입 | POST | api/auth/register | [바로가기](/src/api/auth/README.md) | None |
42 -| auth | 로그인 확인 | GET | api/auth/check | [바로가기](/src/api/auth/README.md) | None | 42 +| auth | 로그인 확인 | GET | api/auth/check | [바로가기](/src/api/auth/README.md) | None |
43 +| challenge | 특정 챌린지 조회(이름) | POST | api/challenge/getChallenge | [바로가기]() | None |
......
...@@ -402,12 +402,12 @@ ...@@ -402,12 +402,12 @@
402 } 402 }
403 }, 403 },
404 "bcrypt": { 404 "bcrypt": {
405 - "version": "3.0.8", 405 + "version": "5.0.0",
406 - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-3.0.8.tgz", 406 + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.0.0.tgz",
407 - "integrity": "sha512-jKV6RvLhI36TQnPDvUFqBEnGX9c8dRRygKxCZu7E+MgLfKZbmmXL8a7/SFFOyHoPNX9nV81cKRC5tbQfvEQtpw==", 407 + "integrity": "sha512-jB0yCBl4W/kVHM2whjfyqnxTmOHkCX4kHEa5nYKSoGeYe8YrjTYTc87/6bwt1g8cmV0QrbhKriETg9jWtcREhg==",
408 "requires": { 408 "requires": {
409 - "nan": "2.14.0", 409 + "node-addon-api": "^3.0.0",
410 - "node-pre-gyp": "0.14.0" 410 + "node-pre-gyp": "0.15.0"
411 } 411 }
412 }, 412 },
413 "bcrypt-pbkdf": { 413 "bcrypt-pbkdf": {
...@@ -2415,11 +2415,6 @@ ...@@ -2415,11 +2415,6 @@
2415 "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 2415 "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
2416 "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 2416 "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
2417 }, 2417 },
2418 - "nan": {
2419 - "version": "2.14.0",
2420 - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
2421 - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg=="
2422 - },
2423 "natural-compare": { 2418 "natural-compare": {
2424 "version": "1.4.0", 2419 "version": "1.4.0",
2425 "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 2420 "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
...@@ -2451,14 +2446,19 @@ ...@@ -2451,14 +2446,19 @@
2451 "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 2446 "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
2452 "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" 2447 "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
2453 }, 2448 },
2449 + "node-addon-api": {
2450 + "version": "3.0.0",
2451 + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.0.0.tgz",
2452 + "integrity": "sha512-sSHCgWfJ+Lui/u+0msF3oyCgvdkhxDbkCS6Q8uiJquzOimkJBvX6hl5aSSA7DR1XbMpdM8r7phjcF63sF4rkKg=="
2453 + },
2454 "node-pre-gyp": { 2454 "node-pre-gyp": {
2455 - "version": "0.14.0", 2455 + "version": "0.15.0",
2456 - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz", 2456 + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.15.0.tgz",
2457 - "integrity": "sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==", 2457 + "integrity": "sha512-7QcZa8/fpaU/BKenjcaeFF9hLz2+7S9AqyXFhlH/rilsQ/hPZKK32RtR5EQHJElgu+q5RfbJ34KriI79UWaorA==",
2458 "requires": { 2458 "requires": {
2459 "detect-libc": "^1.0.2", 2459 "detect-libc": "^1.0.2",
2460 - "mkdirp": "^0.5.1", 2460 + "mkdirp": "^0.5.3",
2461 - "needle": "^2.2.1", 2461 + "needle": "^2.5.0",
2462 "nopt": "^4.0.1", 2462 "nopt": "^4.0.1",
2463 "npm-packlist": "^1.1.6", 2463 "npm-packlist": "^1.1.6",
2464 "npmlog": "^4.0.2", 2464 "npmlog": "^4.0.2",
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
5 "license": "MIT", 5 "license": "MIT",
6 "dependencies": { 6 "dependencies": {
7 "axios": "^0.19.2", 7 "axios": "^0.19.2",
8 - "bcrypt": "^3.0.0", 8 + "bcrypt": "^5.0.0",
9 "body-parser": "^1.19.0", 9 "body-parser": "^1.19.0",
10 "cheerio": "^1.0.0-rc.3", 10 "cheerio": "^1.0.0-rc.3",
11 "cookie-parser": "^1.4.5", 11 "cookie-parser": "^1.4.5",
......
1 const Joi = require("joi"); 1 const Joi = require("joi");
2 const User = require("../../models/user"); 2 const User = require("../../models/user");
3 -const Profile = require("../../models/profile");
4 /* 3 /*
5 POST /api/auth/register 4 POST /api/auth/register
6 { 5 {
...@@ -28,14 +27,10 @@ exports.register = async (ctx) => { ...@@ -28,14 +27,10 @@ exports.register = async (ctx) => {
28 ctx.status = 409; 27 ctx.status = 409;
29 return; 28 return;
30 } 29 }
31 - const profile = new Profile({
32 - username,
33 - });
34 const user = new User({ 30 const user = new User({
35 username, 31 username,
36 }); 32 });
37 await user.setPassword(password); 33 await user.setPassword(password);
38 - await profile.save();
39 await user.save(); 34 await user.save();
40 ctx.body = user.serialize(); 35 ctx.body = user.serialize();
41 36
......
1 +const Challenge = require("../../models/challenge");
2 +const Session = require("../../models/session");
3 +const Participation = require("../../models/participation");
4 +const Group = require("../../models/group");
5 +const User = require('../../models/user');
6 +
7 +const Joi = require("joi");
8 +/*POST /api/challenge/getChallenge
9 +{
10 + challengeName: "challengeName"
11 +}
12 +*/
13 +exports.getChallenge = async (ctx) => {
14 + try {
15 + const { challengeName } = ctx.request.body;
16 + const challenge = await Challenge.findByChallengeName(challengeName).select('-_id');
17 + if (!challenge) {
18 + ctx.status = 401;
19 + return;
20 + }
21 + ctx.body = challenge;
22 + } catch (e) {
23 + ctx.throw(500, e);
24 + }
25 +};
26 +/*POST /api/challenge/addChallenge
27 +{
28 + challengeName: "challengeName",
29 + startDate: Date Object,
30 + endDate: Date Object,
31 + durationPerSession: "2w", // '1d' means one day per session, '2w' means 2 weeks per session, '3m' means 3 months per session.
32 + goalPerSession: 3,
33 +}
34 +*/
35 +exports.addChallenge = async (ctx) => {
36 + const schema = Joi.object()
37 + .keys({
38 + challengeName: Joi.string(),
39 + startDate: Joi.date(),
40 + endDate: Joi.date(),
41 + durationPerSession: Joi.string(),
42 + goalPerSession: Joi.number()
43 + })
44 + .unknown();
45 + const result = Joi.validate(ctx.request.body, schema);
46 +
47 + if (result.error) {
48 + ctx.status = 400;
49 + ctx.body = result.error;
50 + return;
51 + }
52 + let {
53 + challengeName,
54 + startDate,
55 + endDate,
56 + durationPerSession,
57 + goalPerSession,
58 + } = ctx.request.body;
59 +
60 + try {
61 + const isChallengeExist = await Challenge.findByChallengeName(challengeName).select('-_id');
62 +
63 + if (isChallengeExist) {
64 + ctx.status = 409;
65 + return;
66 + }
67 + const challenge = new Challenge({
68 + challengeName,
69 + startDate,
70 + endDate,
71 + durationPerSession,
72 + goalPerSession,
73 + });
74 +
75 + await challenge.save();
76 +
77 + const newChallenge=await Challenge.findByChallengeName(challengeName);
78 + const newChallenge_id=newChallenge._id;
79 + const timeStep=Number(durationPerSession.slice(0,-1))
80 + if(typeof(startDate)=='string'){
81 + startDate=new Date(startDate);
82 + }
83 + if(typeof(endDate)=='string'){
84 + endDate=new Date(endDate);
85 + }
86 + for(let s_date=new Date(startDate);s_date<endDate;){
87 + let e_date=new Date(s_date);
88 + if(durationPerSession[durationPerSession.length-1]==='d'){
89 + console.log('day');
90 + e_date.setDate(s_date.getDate()+timeStep);
91 + }
92 + else if(durationPerSession[durationPerSession.length-1]==='w'){
93 + console.log('week');
94 + e_date.setDate(s_date.getDate()+timeStep*7);
95 + }
96 + else if(durationPerSession[durationPerSession.length-1]==='m'){
97 + console.log('month');
98 + e_date.setMonth(s_date.getMonth()+timeStep);
99 + }
100 + e_date.setMinutes(e_date.getMinutes()-1);
101 + if(e_date>endDate){
102 + break;
103 + }
104 + let status="";
105 + if (s_date>new Date()){
106 + status="enrolled";
107 + }
108 + else if (s_date<=new Date() && new Date() <= e_date){
109 + status="progress";
110 + }
111 + else{
112 + status="end";
113 + }
114 + console.log(`start:${s_date}\nend:${e_date}`);
115 + const session=new Session({
116 + challengeId:newChallenge_id,
117 + sessionStartDate:s_date,
118 + sessionEndDate:e_date,
119 + status:status,
120 + });
121 + await session.save();
122 + s_date=new Date(e_date);
123 + s_date.setMinutes(s_date.getMinutes()+1);
124 + }
125 + ctx.body = challenge;
126 + } catch (e) {
127 + ctx.throw(500, e);
128 + }
129 +};
130 +
131 +
132 +/* GET /api/challenge/list?status
133 +query string status can be in ['all','enrolled','progress','end']
134 +*/
135 +exports.list = async (ctx) => {
136 + try{
137 + const status = ctx.query.status;
138 + if (status!=='all'){
139 + const challenges = await Challenge.find({status:status}).select('-_id');
140 + ctx.body = challenges;
141 + }
142 + else {
143 + const challenges = await Challenge.find({}).select('-_id');
144 + ctx.body = challenges;
145 + }
146 + }
147 + catch(e){
148 + ctx.throw(500,e);
149 + }
150 +};
151 +
152 +/* POST /api/challenge/participate
153 +{
154 + username: 'username',
155 + challengeName: 'challengename'
156 +}
157 +*/
158 +
159 +exports.participate=async (ctx)=>{
160 + try{
161 + /*
162 + TODO: access token validation,
163 + recommend:get username from access_token
164 + */
165 + console.log(ctx.request.body);
166 + const {username,challengeName}=ctx.request.body;
167 + const challenge=await Challenge.findByChallengeName(challengeName);
168 + const challenge_id=challenge._id;
169 + const user=await User.findByUsername(username);
170 + const user_id=user._id;
171 + const newGroup=new Group({
172 + members:[user_id],
173 + });
174 + let newGroup_id=""
175 + await newGroup.save(async (err,product)=>{
176 + if(err){
177 + throw err;
178 + }
179 + newGroup_id=product._id;
180 + const sessions=await Session.findByChallengeId(challenge_id);
181 + sessions.forEach(async (elem) => {
182 + const newParticipation=new Participation({
183 + sessionId:elem._id,
184 + groupId:newGroup_id,
185 + problems:[],
186 + });
187 + await newParticipation.save();
188 + });
189 + });
190 + }
191 + catch(e){
192 + console.error(e);
193 + ctx.throw(500,e);
194 + }
195 +};
...\ No newline at end of file ...\ No newline at end of file
1 +const Router = require('koa-router');
2 +const challenge = new Router();
3 +const challengeCtrl = require('./challege.ctrl');
4 +
5 +challenge.post("/getchallenge",challengeCtrl.getChallenge);
6 +challenge.post("/addchallenge",challengeCtrl.addChallenge);
7 +challenge.get("/list",challengeCtrl.list);
8 +challenge.post("/participate",challengeCtrl.participate);
9 +
10 +module.exports = challenge;
...\ No newline at end of file ...\ No newline at end of file
...@@ -6,11 +6,13 @@ const friend = require("./friend"); ...@@ -6,11 +6,13 @@ const friend = require("./friend");
6 const notify = require("./notify"); 6 const notify = require("./notify");
7 const user = require("./user"); 7 const user = require("./user");
8 const profile = require("./profile"); 8 const profile = require("./profile");
9 +const challenge = require("./challenge");
9 10
10 api.use("/auth", auth.routes()); 11 api.use("/auth", auth.routes());
11 api.use("/friend", friend.routes()); 12 api.use("/friend", friend.routes());
12 api.use("/notify", notify.routes()); 13 api.use("/notify", notify.routes());
13 api.use("/user", user.routes()); 14 api.use("/user", user.routes());
14 api.use("/profile", profile.routes()); 15 api.use("/profile", profile.routes());
16 +api.use("/challenge",challenge.routes());
15 17
16 module.exports = api; 18 module.exports = api;
......
1 -const Profile = require("../../models/profile"); 1 +const User = require("../../models/user");
2 const sendSlack = require("../../util/sendSlack"); 2 const sendSlack = require("../../util/sendSlack");
3 const problem_set = require("../../data/problem_set"); 3 const problem_set = require("../../data/problem_set");
4 const compareBJ = require("../../util/compareBJ"); 4 const compareBJ = require("../../util/compareBJ");
...@@ -12,7 +12,7 @@ exports.slackGoal = async (ctx) => { ...@@ -12,7 +12,7 @@ exports.slackGoal = async (ctx) => {
12 try { 12 try {
13 const { username } = ctx.request.body; 13 const { username } = ctx.request.body;
14 14
15 - const profile = await Profile.findByUsername(username); 15 + const profile = await User.findByUsername(username);
16 if (!profile) { 16 if (!profile) {
17 ctx.status = 401; 17 ctx.status = 401;
18 return; 18 return;
...@@ -62,7 +62,7 @@ exports.slackRecommend = async (ctx) => { ...@@ -62,7 +62,7 @@ exports.slackRecommend = async (ctx) => {
62 console.log("1"); 62 console.log("1");
63 const { username } = ctx.request.body; 63 const { username } = ctx.request.body;
64 64
65 - const profile = await Profile.findByUsername(username); 65 + const profile = await User.findByUsername(username);
66 if (!profile) { 66 if (!profile) {
67 ctx.status = 401; 67 ctx.status = 401;
68 return; 68 return;
......
1 -const Profile = require("../../models/profile"); 1 +const User = require("../../models/user");
2 const mongoose = require("mongoose"); 2 const mongoose = require("mongoose");
3 const getBJ = require("../../util/getBJ"); 3 const getBJ = require("../../util/getBJ");
4 const Joi = require("joi"); 4 const Joi = require("joi");
...@@ -16,6 +16,7 @@ exports.checkObjectId = (ctx, next) => { ...@@ -16,6 +16,7 @@ exports.checkObjectId = (ctx, next) => {
16 } 16 }
17 return next(); 17 return next();
18 }; 18 };
19 +
19 /*POST /api/profile/getprofile 20 /*POST /api/profile/getprofile
20 { 21 {
21 username: "username" 22 username: "username"
...@@ -24,7 +25,7 @@ exports.checkObjectId = (ctx, next) => { ...@@ -24,7 +25,7 @@ exports.checkObjectId = (ctx, next) => {
24 exports.getProfile = async (ctx) => { 25 exports.getProfile = async (ctx) => {
25 try { 26 try {
26 const { username } = ctx.request.body; 27 const { username } = ctx.request.body;
27 - const profile = await Profile.findByUsername(username); 28 + const profile = await User.findByUsername(username);
28 if (!profile) { 29 if (!profile) {
29 ctx.status = 401; 30 ctx.status = 401;
30 return; 31 return;
...@@ -50,7 +51,6 @@ exports.setProfile = async (ctx) => { ...@@ -50,7 +51,6 @@ exports.setProfile = async (ctx) => {
50 //freindList: Joi.array().items(Joi.string()), 51 //freindList: Joi.array().items(Joi.string()),
51 }) 52 })
52 .unknown(); 53 .unknown();
53 - console.log(ctx.request.body);
54 const result = Joi.validate(ctx.request.body, schema); 54 const result = Joi.validate(ctx.request.body, schema);
55 if (result.error) { 55 if (result.error) {
56 ctx.status = 400; 56 ctx.status = 400;
...@@ -59,7 +59,7 @@ exports.setProfile = async (ctx) => { ...@@ -59,7 +59,7 @@ exports.setProfile = async (ctx) => {
59 } 59 }
60 60
61 try { 61 try {
62 - const profile = await Profile.findOneAndUpdate( 62 + const profile = await User.findOneAndUpdate(
63 { username: ctx.request.body.username }, 63 { username: ctx.request.body.username },
64 ctx.request.body, 64 ctx.request.body,
65 { 65 {
...@@ -91,7 +91,7 @@ exports.syncBJ = async function (ctx) { ...@@ -91,7 +91,7 @@ exports.syncBJ = async function (ctx) {
91 } 91 }
92 92
93 try { 93 try {
94 - const profile = await Profile.findByUsername(username); 94 + const profile = await User.findByUsername(username);
95 if (!profile) { 95 if (!profile) {
96 ctx.status = 401; 96 ctx.status = 401;
97 return; 97 return;
...@@ -99,7 +99,7 @@ exports.syncBJ = async function (ctx) { ...@@ -99,7 +99,7 @@ exports.syncBJ = async function (ctx) {
99 const BJID = await profile.getBJID(); 99 const BJID = await profile.getBJID();
100 let BJdata = await getBJ.getBJ(BJID); 100 let BJdata = await getBJ.getBJ(BJID);
101 let BJdata_date = await analyzeBJ.analyzeBJ(BJdata); 101 let BJdata_date = await analyzeBJ.analyzeBJ(BJdata);
102 - const updateprofile = await Profile.findOneAndUpdate( 102 + const updateprofile = await User.findOneAndUpdate(
103 { username: username }, 103 { username: username },
104 { solvedBJ: BJdata, solvedBJ_date: BJdata_date }, 104 { solvedBJ: BJdata, solvedBJ_date: BJdata_date },
105 { new: true } 105 { new: true }
...@@ -124,7 +124,7 @@ exports.recommend = async (ctx) => { ...@@ -124,7 +124,7 @@ exports.recommend = async (ctx) => {
124 return; 124 return;
125 } 125 }
126 try { 126 try {
127 - const profile = await Profile.findByUsername(username); 127 + const profile = await User.findByUsername(username);
128 if (!profile) { 128 if (!profile) {
129 ctx.status = 401; 129 ctx.status = 401;
130 return; 130 return;
...@@ -134,7 +134,7 @@ exports.recommend = async (ctx) => { ...@@ -134,7 +134,7 @@ exports.recommend = async (ctx) => {
134 problem_set.problem_set 134 problem_set.problem_set
135 ); 135 );
136 ctx.body = compareBJ.randomItem(unsolved_data); 136 ctx.body = compareBJ.randomItem(unsolved_data);
137 - //데이터가 비었을 떄 예외처리 필요 137 + //TODO: 데이터가 비었을 떄 예외처리 필요
138 } catch (e) { 138 } catch (e) {
139 ctx.throw(500, e); 139 ctx.throw(500, e);
140 } 140 }
......
...@@ -2,61 +2,48 @@ const mongoose = require("mongoose"); ...@@ -2,61 +2,48 @@ const mongoose = require("mongoose");
2 2
3 const { Schema } = mongoose; 3 const { Schema } = mongoose;
4 4
5 -const GroupSchema = new Schema({ 5 +const ChallengeSchema=new Schema({
6 - members: { type: [String] }, 6 + challengeName: {type: String, required: true},
7 + startDate: {type: Object, required: true},
8 + endDate: {type: Object, required: true},
9 + durationPerSession: {type: String, required: true}, // '1d' means one day per session, '2w' means 2 weeks per session, '3m' means 3 months per session.
10 + goalPerSession: {type: Number, required:true}, // number of problems for one session
11 + status: { type: String }
12 +},{
13 + collection: 'challenge'
7 }); 14 });
8 15
9 -const ChallengeSchema = new Schema({ 16 +ChallengeSchema.statics.findByChallengeName=function(challengeName){
10 - challengeName: { type: String, required: true }, 17 + return this.findOne({challengeName:challengeName});
11 - startDate: { type: Object, required: true }, 18 +}
12 - endDate: { type: Object, required: true },
13 - durationPerSession: { type: String, required: true }, // '1d' means one day per session, '2w' means 2 weeks per session, '3m' means 3 months per session.
14 - goalPerSession: { type: Number, required: true }, // number of problems for one session
15 - groups: { type: [GroupSchema], required: true }, // groups attending challenge, group of only one member supposed to be single
16 -});
17 -
18 -ChallengeSchema.statics.findByChallengeName = function (challengeName) {
19 - return this.findOne({ challengeName: challengeName });
20 -};
21 -
22 -ChallengeSchema.methods.addNewGroup = function (group) {
23 - this.groups.push(group);
24 - return this.save();
25 -};
26 -
27 -ChallengeSchema.methods.removeGroup = function (group_id) {
28 - const idx = this.groups.findIndex((item) => item._id === group_id);
29 - this.groups.splice(idx, 1);
30 - return this.save();
31 -};
32 19
33 -ChallengeSchema.methods.getChallengeName = function () { 20 +ChallengeSchema.methods.getChallengeName=function(){
34 - return this.challengeName; 21 + return this.challengeName;
35 -}; 22 +}
36 23
37 -ChallengeSchema.methods.getStartDate = function () { 24 +ChallengeSchema.methods.getStartDate=function(){
38 - return this.startDate; 25 + return this.startDate;
39 -}; 26 +}
40 27
41 -ChallengeSchema.methods.getEndDate = function () { 28 +ChallengeSchema.methods.getEndDate=function(){
42 - return this.endDate; 29 + return this.endDate;
43 -}; 30 +}
44 31
45 -ChallengeSchema.methods.getDurationPerSession = function () { 32 +ChallengeSchema.method.getDurationPerSession=function(){
46 - return this.durationPerSession; 33 + return this.durationPerSession;
47 -}; 34 +}
48 35
49 -ChallengeSchema.methods.getGoalPerSession = function () { 36 +ChallengeSchema.methods.getGoalPerSession=function(){
50 - return this.goalPerSession; 37 + return this.goalPerSession;
51 -}; 38 +}
52 39
53 -ChallengeSchema.methods.getGroups = function () { 40 +ChallengeSchema.methods.getStatus=function(){
54 - return this.groups; 41 + return this.status;
55 -}; 42 +}
56 43
57 -ChallengeSchema.methods.serialize = function () { 44 +ChallengeSchema.methods.serialize=function(){
58 - return this.toJSON(); 45 + return this.toJSON();
59 -}; 46 +}
60 47
61 -const Challenge = mongoose.model("Challenge", ChallengeSchema); 48 +const Challenge = mongoose.model('Challenge', ChallengeSchema);
62 -module.exports = Challenge; 49 +module.exports = Challenge;
...\ No newline at end of file ...\ No newline at end of file
......
1 +const mongoose = require("mongoose");
2 +
3 +const { Schema } = mongoose;
4 +
5 +const GroupSchema = new Schema({
6 + members: [{ type: Schema.Types.ObjectId, ref: 'User' }]
7 +},{
8 + collection: 'group'
9 +});
10 +
11 +GroupSchema.methods.addGroupMemeber=function(user){
12 + this.members.push(user._id);
13 + return this.save();
14 +}
15 +
16 +GroupSchema.methods.getMembers=function(){
17 + return this.members;
18 +}
19 +
20 +GroupSchema.methods.serialize=function(){
21 + return this.toJSON();
22 +}
23 +
24 +const Group = mongoose.model('Group',GroupSchema);
25 +module.exports = Group;
...\ No newline at end of file ...\ No newline at end of file
1 +const mongoose = require("mongoose");
2 +
3 +const { Schema } = mongoose;
4 +
5 +const SelectedProblemSchema=new Schema({
6 + problemNum: {type: Number, required: true},
7 + isSolved: {type:Boolean, default: false},
8 +},{
9 + _id: false
10 +});
11 +
12 +const ParticipationSchema = new Schema({
13 + sessionId: { type: Schema.Types.ObjectId, ref: 'Session' },
14 + groupId: { type: Schema.Types.ObjectId, ref: 'Group' },
15 + problems: [{type:SelectedProblemSchema}]
16 +},{
17 + collection: 'particiaption'
18 +});
19 +
20 +ParticipationSchema.statics.findBySessionId=function(session){
21 + return this.find({sessionId:session._id});
22 +}
23 +
24 +ParticipationSchema.statics.findByGroupId=function(group){
25 + return this.find({groupId:group._id});
26 +}
27 +
28 +ParticipationSchema.methods.addProblem=function(problem){
29 + this.problems.push({problemNum:problem.problemNum,isSolved:problem.isSolved});
30 +}
31 +
32 +const Participation = mongoose.model('Participation', ParticipationSchema);
33 +module.exports = Participation;
...\ No newline at end of file ...\ No newline at end of file
...@@ -8,7 +8,10 @@ const ProblemSchema=new Schema({ ...@@ -8,7 +8,10 @@ const ProblemSchema=new Schema({
8 solvedacLevel: {type: Number}, 8 solvedacLevel: {type: Number},
9 sumbitNum: {type: Number, required: true}, 9 sumbitNum: {type: Number, required: true},
10 correctNum: {type: Number, required: true}, 10 correctNum: {type: Number, required: true},
11 - category: {type:[String]} 11 + count: { type: Number },
12 + category: [{ type:String }],
13 +},{
14 + collection: 'problem'
12 }); 15 });
13 16
14 ProblemSchema.statics.findByProblemNum=function(problemNum){ 17 ProblemSchema.statics.findByProblemNum=function(problemNum){
...@@ -46,6 +49,10 @@ ProblemSchema.methods.getCorrectNum=function(){ ...@@ -46,6 +49,10 @@ ProblemSchema.methods.getCorrectNum=function(){
46 return this.correctNum; 49 return this.correctNum;
47 } 50 }
48 51
52 +ProblemSchema.methods.getCount=function(){
53 + return this.count;
54 +}
55 +
49 ProblemSchema.methods.getCategory=function(){ 56 ProblemSchema.methods.getCategory=function(){
50 return this.category; 57 return this.category;
51 } 58 }
...@@ -54,5 +61,5 @@ ProblemSchema.methods.serialize=function(){ ...@@ -54,5 +61,5 @@ ProblemSchema.methods.serialize=function(){
54 return this.toJSON(); 61 return this.toJSON();
55 } 62 }
56 63
57 -const Problem=mongoose.model('Problem',ProblemSchema);
58 -module.exports=Problem;
...\ No newline at end of file ...\ No newline at end of file
64 +const Problem = mongoose.model('Problem',ProblemSchema);
65 +module.exports = Problem;
...\ No newline at end of file ...\ No newline at end of file
......
1 -const mongoose = require("mongoose");
2 -
3 -const { Schema } = mongoose;
4 -
5 -const ProfileSchema = new Schema({
6 - username: { type: String, required: true, unique: true },
7 - userBJID: String,
8 - solvedBJ: Object,
9 - solvedBJ_date: Object,
10 - friendList: [String],
11 - slackWebHookURL: String,
12 - goalNum: Number,
13 -});
14 -ProfileSchema.statics.findByUsername = function (username) {
15 - return this.findOne({ username });
16 -};
17 -ProfileSchema.methods.getBJID = function () {
18 - return this.userBJID;
19 -};
20 -ProfileSchema.methods.getBJdata = function () {
21 - return this.solvedBJ;
22 -};
23 -ProfileSchema.methods.getslackURL = function () {
24 - return this.slackWebHookURL;
25 -};
26 -ProfileSchema.methods.getgoalNum = function () {
27 - return this.goalNum;
28 -};
29 -ProfileSchema.methods.getTodaySovled = function () {
30 - if (this.solvedBJ_date) {
31 - return this.solvedBJ_date.presentNum;
32 - }
33 -};
34 -
35 -ProfileSchema.methods.serialize = function () {
36 - const data = this.toJSON();
37 - return data;
38 -};
39 -const Profile = mongoose.model("Profile", ProfileSchema);
40 -module.exports = Profile;
1 +const mongoose = require("mongoose");
2 +
3 +const { Schema } = mongoose;
4 +
5 +const SessionSchema = new Schema({
6 + challengeId: { type: Schema.Types.ObjectId, ref: 'Challenge' },
7 + sessionStartDate: { type: Object },
8 + sessionEndDate: { type: Object },
9 + status: { type: String }
10 +},{
11 + collection: 'session'
12 +});
13 +
14 +SessionSchema.statics.findByChallengeId=function(challenge){
15 + return this.find({challengeId:challenge._id});
16 +}
17 +
18 +SessionSchema.methods.getSessionStartDate=function(){
19 + return this.sessionStartDate;
20 +}
21 +
22 +SessionSchema.methods.getSessionEndDate=function(){
23 + return this.sessionEndDate;
24 +}
25 +
26 +SessionSchema.methods.getStatus=function(){
27 + return this.status;
28 +}
29 +
30 +SessionSchema.methods.serialize=function(){
31 + return this.toJSON();
32 +}
33 +
34 +const Session = mongoose.model('Session', SessionSchema);
35 +module.exports = Session;
...\ No newline at end of file ...\ No newline at end of file
...@@ -7,8 +7,25 @@ const Schema = mongoose.Schema; ...@@ -7,8 +7,25 @@ const Schema = mongoose.Schema;
7 const UserSchema = new Schema({ 7 const UserSchema = new Schema({
8 username: String, 8 username: String,
9 hashedPassword: String, 9 hashedPassword: String,
10 + userBJID: String,
11 + sovledBJ: Object,
12 + solvedBJ_date: Object,
13 + friendList: [{ type: Schema.Types.ObjectId, ref: 'User' }],
14 + slackWebHookURL: String,
15 + goalNum: Number,
16 +},{
17 + collection: 'user'
10 }); 18 });
11 19
20 +UserSchema.statics.findByUsername = function (username) {
21 + return this.findOne({ username });
22 +};
23 +
24 +UserSchema.methods.addFriend=function(friend){
25 + this.friendList.push(friend._id);
26 + return this.save();
27 +}
28 +
12 UserSchema.methods.setPassword = async function (password) { 29 UserSchema.methods.setPassword = async function (password) {
13 const hash = await bcrypt.hash(password, 10); 30 const hash = await bcrypt.hash(password, 10);
14 this.hashedPassword = hash; 31 this.hashedPassword = hash;
...@@ -17,14 +34,13 @@ UserSchema.methods.checkPassword = async function (password) { ...@@ -17,14 +34,13 @@ UserSchema.methods.checkPassword = async function (password) {
17 const result = await bcrypt.compare(password, this.hashedPassword); 34 const result = await bcrypt.compare(password, this.hashedPassword);
18 return result; 35 return result;
19 }; 36 };
20 -UserSchema.statics.findByUsername = function (username) { 37 +
21 - return this.findOne({ username });
22 -};
23 UserSchema.methods.serialize = function () { 38 UserSchema.methods.serialize = function () {
24 const data = this.toJSON(); 39 const data = this.toJSON();
25 delete data.hashedPassword; 40 delete data.hashedPassword;
26 return data; 41 return data;
27 }; 42 };
43 +
28 UserSchema.methods.generateToken = function () { 44 UserSchema.methods.generateToken = function () {
29 const token = jwt.sign( 45 const token = jwt.sign(
30 { 46 {
...@@ -38,5 +54,32 @@ UserSchema.methods.generateToken = function () { ...@@ -38,5 +54,32 @@ UserSchema.methods.generateToken = function () {
38 ); 54 );
39 return token; 55 return token;
40 }; 56 };
57 +
58 +UserSchema.statics.findByUsername = function (username) {
59 + return this.findOne({ username });
60 +};
61 +
62 +UserSchema.methods.getBJID = function () {
63 + return this.userBJID;
64 +};
65 +
66 +UserSchema.methods.getBJdata = function () {
67 + return this.solvedBJ;
68 +};
69 +
70 +UserSchema.methods.getslackURL = function () {
71 + return this.slackWebHookURL;
72 +};
73 +
74 +UserSchema.methods.getgoalNum = function () {
75 + return this.goalNum;
76 +};
77 +
78 +UserSchema.methods.getTodaySovled = function () {
79 + if (this.solvedBJ_date) {
80 + return this.solvedBJ_date.presentNum;
81 + }
82 +};
83 +
41 const User = mongoose.model("User", UserSchema); 84 const User = mongoose.model("User", UserSchema);
42 module.exports = User; 85 module.exports = User;
......
...@@ -134,10 +134,10 @@ acorn-jsx@^5.2.0: ...@@ -134,10 +134,10 @@ acorn-jsx@^5.2.0:
134 resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.2.0.tgz#4c66069173d6fdd68ed85239fc256226182b2ebe" 134 resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.2.0.tgz#4c66069173d6fdd68ed85239fc256226182b2ebe"
135 integrity sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ== 135 integrity sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==
136 136
137 -acorn@^7.1.1: 137 +acorn@^7.3.1:
138 - version "7.2.0" 138 + version "7.4.0"
139 - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.2.0.tgz#17ea7e40d7c8640ff54a694c889c26f31704effe" 139 + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.0.tgz#e1ad486e6c54501634c6c397c5c121daa383607c"
140 - integrity sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ== 140 + integrity sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==
141 141
142 agent-base@2: 142 agent-base@2:
143 version "2.1.1" 143 version "2.1.1"
...@@ -164,12 +164,10 @@ ansi-align@^3.0.0: ...@@ -164,12 +164,10 @@ ansi-align@^3.0.0:
164 dependencies: 164 dependencies:
165 string-width "^3.0.0" 165 string-width "^3.0.0"
166 166
167 -ansi-escapes@^4.2.1: 167 +ansi-colors@^4.1.1:
168 - version "4.3.1" 168 + version "4.1.1"
169 - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.1.tgz#a5c47cc43181f1f38ffd7076837700d395522a61" 169 + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
170 - integrity sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA== 170 + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==
171 - dependencies:
172 - type-fest "^0.11.0"
173 171
174 ansi-regex@^2.0.0: 172 ansi-regex@^2.0.0:
175 version "2.1.1" 173 version "2.1.1"
...@@ -471,11 +469,6 @@ chalk@^4.0.0: ...@@ -471,11 +469,6 @@ chalk@^4.0.0:
471 ansi-styles "^4.1.0" 469 ansi-styles "^4.1.0"
472 supports-color "^7.1.0" 470 supports-color "^7.1.0"
473 471
474 -chardet@^0.7.0:
475 - version "0.7.0"
476 - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
477 - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
478 -
479 cheerio@^1.0.0-rc.3: 472 cheerio@^1.0.0-rc.3:
480 version "1.0.0-rc.3" 473 version "1.0.0-rc.3"
481 resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.3.tgz#094636d425b2e9c0f4eb91a46c05630c9a1a8bf6" 474 resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.3.tgz#094636d425b2e9c0f4eb91a46c05630c9a1a8bf6"
...@@ -518,18 +511,6 @@ cli-boxes@^2.2.0: ...@@ -518,18 +511,6 @@ cli-boxes@^2.2.0:
518 resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.0.tgz#538ecae8f9c6ca508e3c3c95b453fe93cb4c168d" 511 resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.0.tgz#538ecae8f9c6ca508e3c3c95b453fe93cb4c168d"
519 integrity sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w== 512 integrity sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==
520 513
521 -cli-cursor@^3.1.0:
522 - version "3.1.0"
523 - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307"
524 - integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==
525 - dependencies:
526 - restore-cursor "^3.1.0"
527 -
528 -cli-width@^2.0.0:
529 - version "2.2.1"
530 - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48"
531 - integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==
532 -
533 clone-response@^1.0.2: 514 clone-response@^1.0.2:
534 version "1.0.2" 515 version "1.0.2"
535 resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" 516 resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b"
...@@ -924,6 +905,13 @@ end-of-stream@^1.1.0: ...@@ -924,6 +905,13 @@ end-of-stream@^1.1.0:
924 dependencies: 905 dependencies:
925 once "^1.4.0" 906 once "^1.4.0"
926 907
908 +enquirer@^2.3.5:
909 + version "2.3.6"
910 + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d"
911 + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==
912 + dependencies:
913 + ansi-colors "^4.1.1"
914 +
927 entities@^1.1.1, entities@~1.1.1: 915 entities@^1.1.1, entities@~1.1.1:
928 version "1.1.2" 916 version "1.1.2"
929 resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" 917 resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
...@@ -956,18 +944,18 @@ eslint-config-prettier@^6.11.0: ...@@ -956,18 +944,18 @@ eslint-config-prettier@^6.11.0:
956 dependencies: 944 dependencies:
957 get-stdin "^6.0.0" 945 get-stdin "^6.0.0"
958 946
959 -eslint-scope@^5.0.0: 947 +eslint-scope@^5.1.0:
960 - version "5.0.0" 948 + version "5.1.0"
961 - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9" 949 + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.0.tgz#d0f971dfe59c69e0cada684b23d49dbf82600ce5"
962 - integrity sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw== 950 + integrity sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==
963 dependencies: 951 dependencies:
964 esrecurse "^4.1.0" 952 esrecurse "^4.1.0"
965 estraverse "^4.1.1" 953 estraverse "^4.1.1"
966 954
967 -eslint-utils@^2.0.0: 955 +eslint-utils@^2.1.0:
968 - version "2.0.0" 956 + version "2.1.0"
969 - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.0.0.tgz#7be1cc70f27a72a76cd14aa698bcabed6890e1cd" 957 + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27"
970 - integrity sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA== 958 + integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==
971 dependencies: 959 dependencies:
972 eslint-visitor-keys "^1.1.0" 960 eslint-visitor-keys "^1.1.0"
973 961
...@@ -976,10 +964,15 @@ eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: ...@@ -976,10 +964,15 @@ eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0:
976 resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" 964 resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2"
977 integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== 965 integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==
978 966
979 -eslint@^7.1.0: 967 +eslint-visitor-keys@^1.3.0:
980 - version "7.1.0" 968 + version "1.3.0"
981 - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.1.0.tgz#d9a1df25e5b7859b0a3d86bb05f0940ab676a851" 969 + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e"
982 - integrity sha512-DfS3b8iHMK5z/YLSme8K5cge168I8j8o1uiVmFCgnnjxZQbCGyraF8bMl7Ju4yfBmCuxD7shOF7eqGkcuIHfsA== 970 + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==
971 +
972 +eslint@^7.3.1:
973 + version "7.7.0"
974 + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.7.0.tgz#18beba51411927c4b64da0a8ceadefe4030d6073"
975 + integrity sha512-1KUxLzos0ZVsyL81PnRN335nDtQ8/vZUD6uMtWbF+5zDtjKcsklIi78XoE0MVL93QvWTu+E5y44VyyCsOMBrIg==
983 dependencies: 976 dependencies:
984 "@babel/code-frame" "^7.0.0" 977 "@babel/code-frame" "^7.0.0"
985 ajv "^6.10.0" 978 ajv "^6.10.0"
...@@ -987,10 +980,11 @@ eslint@^7.1.0: ...@@ -987,10 +980,11 @@ eslint@^7.1.0:
987 cross-spawn "^7.0.2" 980 cross-spawn "^7.0.2"
988 debug "^4.0.1" 981 debug "^4.0.1"
989 doctrine "^3.0.0" 982 doctrine "^3.0.0"
990 - eslint-scope "^5.0.0" 983 + enquirer "^2.3.5"
991 - eslint-utils "^2.0.0" 984 + eslint-scope "^5.1.0"
992 - eslint-visitor-keys "^1.1.0" 985 + eslint-utils "^2.1.0"
993 - espree "^7.0.0" 986 + eslint-visitor-keys "^1.3.0"
987 + espree "^7.2.0"
994 esquery "^1.2.0" 988 esquery "^1.2.0"
995 esutils "^2.0.2" 989 esutils "^2.0.2"
996 file-entry-cache "^5.0.1" 990 file-entry-cache "^5.0.1"
...@@ -1000,12 +994,11 @@ eslint@^7.1.0: ...@@ -1000,12 +994,11 @@ eslint@^7.1.0:
1000 ignore "^4.0.6" 994 ignore "^4.0.6"
1001 import-fresh "^3.0.0" 995 import-fresh "^3.0.0"
1002 imurmurhash "^0.1.4" 996 imurmurhash "^0.1.4"
1003 - inquirer "^7.0.0"
1004 is-glob "^4.0.0" 997 is-glob "^4.0.0"
1005 js-yaml "^3.13.1" 998 js-yaml "^3.13.1"
1006 json-stable-stringify-without-jsonify "^1.0.1" 999 json-stable-stringify-without-jsonify "^1.0.1"
1007 levn "^0.4.1" 1000 levn "^0.4.1"
1008 - lodash "^4.17.14" 1001 + lodash "^4.17.19"
1009 minimatch "^3.0.4" 1002 minimatch "^3.0.4"
1010 natural-compare "^1.4.0" 1003 natural-compare "^1.4.0"
1011 optionator "^0.9.1" 1004 optionator "^0.9.1"
...@@ -1018,14 +1011,14 @@ eslint@^7.1.0: ...@@ -1018,14 +1011,14 @@ eslint@^7.1.0:
1018 text-table "^0.2.0" 1011 text-table "^0.2.0"
1019 v8-compile-cache "^2.0.3" 1012 v8-compile-cache "^2.0.3"
1020 1013
1021 -espree@^7.0.0: 1014 +espree@^7.2.0:
1022 - version "7.0.0" 1015 + version "7.2.0"
1023 - resolved "https://registry.yarnpkg.com/espree/-/espree-7.0.0.tgz#8a7a60f218e69f120a842dc24c5a88aa7748a74e" 1016 + resolved "https://registry.yarnpkg.com/espree/-/espree-7.2.0.tgz#1c263d5b513dbad0ac30c4991b93ac354e948d69"
1024 - integrity sha512-/r2XEx5Mw4pgKdyb7GNLQNsu++asx/dltf/CI8RFi9oGHxmQFgvLbc5Op4U6i8Oaj+kdslhJtVlEZeAqH5qOTw== 1017 + integrity sha512-H+cQ3+3JYRMEIOl87e7QdHX70ocly5iW4+dttuR8iYSPr/hXKFb+7dBsZ7+u1adC4VrnPlTkv0+OwuPnDop19g==
1025 dependencies: 1018 dependencies:
1026 - acorn "^7.1.1" 1019 + acorn "^7.3.1"
1027 acorn-jsx "^5.2.0" 1020 acorn-jsx "^5.2.0"
1028 - eslint-visitor-keys "^1.1.0" 1021 + eslint-visitor-keys "^1.3.0"
1029 1022
1030 esprima@^4.0.0: 1023 esprima@^4.0.0:
1031 version "4.0.1" 1024 version "4.0.1"
...@@ -1071,15 +1064,6 @@ extend@3, extend@^3.0.0, extend@~3.0.0, extend@~3.0.2: ...@@ -1071,15 +1064,6 @@ extend@3, extend@^3.0.0, extend@~3.0.0, extend@~3.0.2:
1071 resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" 1064 resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
1072 integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== 1065 integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
1073 1066
1074 -external-editor@^3.0.3:
1075 - version "3.1.0"
1076 - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495"
1077 - integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==
1078 - dependencies:
1079 - chardet "^0.7.0"
1080 - iconv-lite "^0.4.24"
1081 - tmp "^0.0.33"
1082 -
1083 extsprintf@1.3.0: 1067 extsprintf@1.3.0:
1084 version "1.3.0" 1068 version "1.3.0"
1085 resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" 1069 resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
...@@ -1110,13 +1094,6 @@ fast-levenshtein@^2.0.6: ...@@ -1110,13 +1094,6 @@ fast-levenshtein@^2.0.6:
1110 resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" 1094 resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
1111 integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= 1095 integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
1112 1096
1113 -figures@^3.0.0:
1114 - version "3.2.0"
1115 - resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af"
1116 - integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==
1117 - dependencies:
1118 - escape-string-regexp "^1.0.5"
1119 -
1120 file-entry-cache@^5.0.1: 1097 file-entry-cache@^5.0.1:
1121 version "5.0.1" 1098 version "5.0.1"
1122 resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" 1099 resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c"
...@@ -1401,7 +1378,7 @@ https-proxy-agent@^1.0.0: ...@@ -1401,7 +1378,7 @@ https-proxy-agent@^1.0.0:
1401 debug "2" 1378 debug "2"
1402 extend "3" 1379 extend "3"
1403 1380
1404 -iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4: 1381 +iconv-lite@0.4.24, iconv-lite@^0.4.4:
1405 version "0.4.24" 1382 version "0.4.24"
1406 resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" 1383 resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
1407 integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== 1384 integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
...@@ -1476,25 +1453,6 @@ ini@^1.3.5, ini@~1.3.0: ...@@ -1476,25 +1453,6 @@ ini@^1.3.5, ini@~1.3.0:
1476 resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" 1453 resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
1477 integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== 1454 integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
1478 1455
1479 -inquirer@^7.0.0:
1480 - version "7.1.0"
1481 - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.1.0.tgz#1298a01859883e17c7264b82870ae1034f92dd29"
1482 - integrity sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg==
1483 - dependencies:
1484 - ansi-escapes "^4.2.1"
1485 - chalk "^3.0.0"
1486 - cli-cursor "^3.1.0"
1487 - cli-width "^2.0.0"
1488 - external-editor "^3.0.3"
1489 - figures "^3.0.0"
1490 - lodash "^4.17.15"
1491 - mute-stream "0.0.8"
1492 - run-async "^2.4.0"
1493 - rxjs "^6.5.3"
1494 - string-width "^4.1.0"
1495 - strip-ansi "^6.0.0"
1496 - through "^2.3.6"
1497 -
1498 is-binary-path@~2.1.0: 1456 is-binary-path@~2.1.0:
1499 version "2.1.0" 1457 version "2.1.0"
1500 resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" 1458 resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
...@@ -1775,10 +1733,10 @@ koa-router@^9.0.1: ...@@ -1775,10 +1733,10 @@ koa-router@^9.0.1:
1775 methods "^1.1.2" 1733 methods "^1.1.2"
1776 path-to-regexp "^6.1.0" 1734 path-to-regexp "^6.1.0"
1777 1735
1778 -koa@^2.12.0: 1736 +koa@^2.13.0:
1779 - version "2.12.0" 1737 + version "2.13.0"
1780 - resolved "https://registry.yarnpkg.com/koa/-/koa-2.12.0.tgz#c92bfb42defd86f365c31bf63fe918db11fc5c74" 1738 + resolved "https://registry.yarnpkg.com/koa/-/koa-2.13.0.tgz#25217e05efd3358a7e5ddec00f0a380c9b71b501"
1781 - integrity sha512-WlUBj6PXoVhjI5ljMmlyK+eqkbVFW5XQu8twz6bd4WM2E67IwKgPMu5wIFXGxAsZT7sW5xAB54KhY8WAEkLPug== 1739 + integrity sha512-i/XJVOfPw7npbMv67+bOeXr3gPqOAw6uh5wFyNs3QvJ47tUx3M3V9rIE0//WytY42MKz4l/MXKyGkQ2LQTfLUQ==
1782 dependencies: 1740 dependencies:
1783 accepts "^1.3.5" 1741 accepts "^1.3.5"
1784 cache-content-type "^1.0.0" 1742 cache-content-type "^1.0.0"
...@@ -1859,11 +1817,16 @@ lodash@^3.10.1: ...@@ -1859,11 +1817,16 @@ lodash@^3.10.1:
1859 resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" 1817 resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6"
1860 integrity sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y= 1818 integrity sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=
1861 1819
1862 -lodash@^4.15.0, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15: 1820 +lodash@^4.15.0, lodash@^4.17.13, lodash@^4.17.14:
1863 version "4.17.15" 1821 version "4.17.15"
1864 resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" 1822 resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
1865 integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== 1823 integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
1866 1824
1825 +lodash@^4.17.19:
1826 + version "4.17.20"
1827 + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
1828 + integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
1829 +
1867 long-timeout@0.1.1: 1830 long-timeout@0.1.1:
1868 version "0.1.1" 1831 version "0.1.1"
1869 resolved "https://registry.yarnpkg.com/long-timeout/-/long-timeout-0.1.1.tgz#9721d788b47e0bcb5a24c2e2bee1a0da55dab514" 1832 resolved "https://registry.yarnpkg.com/long-timeout/-/long-timeout-0.1.1.tgz#9721d788b47e0bcb5a24c2e2bee1a0da55dab514"
...@@ -1913,11 +1876,6 @@ mime-types@^2.1.12, mime-types@^2.1.18, mime-types@~2.1.19, mime-types@~2.1.24: ...@@ -1913,11 +1876,6 @@ mime-types@^2.1.12, mime-types@^2.1.18, mime-types@~2.1.19, mime-types@~2.1.24:
1913 dependencies: 1876 dependencies:
1914 mime-db "1.44.0" 1877 mime-db "1.44.0"
1915 1878
1916 -mimic-fn@^2.1.0:
1917 - version "2.1.0"
1918 - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
1919 - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
1920 -
1921 mimic-response@^1.0.0, mimic-response@^1.0.1: 1879 mimic-response@^1.0.0, mimic-response@^1.0.1:
1922 version "1.0.1" 1880 version "1.0.1"
1923 resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" 1881 resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b"
...@@ -1969,10 +1927,10 @@ moment-timezone@^0.5.31: ...@@ -1969,10 +1927,10 @@ moment-timezone@^0.5.31:
1969 resolved "https://registry.yarnpkg.com/moment/-/moment-2.27.0.tgz#8bff4e3e26a236220dfe3e36de756b6ebaa0105d" 1927 resolved "https://registry.yarnpkg.com/moment/-/moment-2.27.0.tgz#8bff4e3e26a236220dfe3e36de756b6ebaa0105d"
1970 integrity sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ== 1928 integrity sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ==
1971 1929
1972 -mongodb@3.5.8: 1930 +mongodb@3.6.0:
1973 - version "3.5.8" 1931 + version "3.6.0"
1974 - resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-3.5.8.tgz#34550856449b745d145873734bf922c12d6b9caa" 1932 + resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-3.6.0.tgz#babd7172ec717e2ed3f85e079b3f1aa29dce4724"
1975 - integrity sha512-jz7mR58z66JKL8Px4ZY+FXbgB7d0a0hEGCT7kw8iye46/gsqPrOEpZOswwJ2BQlfzsrCLKdsF9UcaUfGVN2HrQ== 1933 + integrity sha512-/XWWub1mHZVoqEsUppE0GV7u9kanLvHxho6EvBxQbShXTKYF9trhZC2NzbulRGeG7xMJHD8IOWRcdKx5LPjAjQ==
1976 dependencies: 1934 dependencies:
1977 bl "^2.2.0" 1935 bl "^2.2.0"
1978 bson "^1.1.4" 1936 bson "^1.1.4"
...@@ -1987,20 +1945,20 @@ mongoose-legacy-pluralize@1.0.2: ...@@ -1987,20 +1945,20 @@ mongoose-legacy-pluralize@1.0.2:
1987 resolved "https://registry.yarnpkg.com/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz#3ba9f91fa507b5186d399fb40854bff18fb563e4" 1945 resolved "https://registry.yarnpkg.com/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz#3ba9f91fa507b5186d399fb40854bff18fb563e4"
1988 integrity sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ== 1946 integrity sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==
1989 1947
1990 -mongoose@^5.9.17: 1948 +mongoose@^5.9.20:
1991 - version "5.9.17" 1949 + version "5.10.0"
1992 - resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-5.9.17.tgz#9b74659481807cd9ff5b9c120cdb5087cbbd92bd" 1950 + resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-5.10.0.tgz#05a35f5a3d8485613c9988aeb9548285a97083f7"
1993 - integrity sha512-9EDmTiKrOu/41twlPWUA1aOsdxSN6PRIdFwTpLu4MjyNcJ/vuBE+VewKrN1jsD4oXO5rB8bMYtYxVmJQ02SrPg== 1951 + integrity sha512-5itAvBMVDG4+zTDtuLg/IyoTxEMgvpOSHnigQ9Cyh8LR4BEgMAChJj7JSaGkg+tr1AjCSY9DgSdU8bHqCOoxXg==
1994 dependencies: 1952 dependencies:
1995 bson "^1.1.4" 1953 bson "^1.1.4"
1996 kareem "2.3.1" 1954 kareem "2.3.1"
1997 - mongodb "3.5.8" 1955 + mongodb "3.6.0"
1998 mongoose-legacy-pluralize "1.0.2" 1956 mongoose-legacy-pluralize "1.0.2"
1999 mpath "0.7.0" 1957 mpath "0.7.0"
2000 mquery "3.2.2" 1958 mquery "3.2.2"
2001 ms "2.1.2" 1959 ms "2.1.2"
2002 regexp-clone "1.0.0" 1960 regexp-clone "1.0.0"
2003 - safe-buffer "5.1.2" 1961 + safe-buffer "5.2.1"
2004 sift "7.0.1" 1962 sift "7.0.1"
2005 sliced "1.0.1" 1963 sliced "1.0.1"
2006 1964
...@@ -2041,11 +1999,6 @@ ms@2.1.2, ms@^2.1.1: ...@@ -2041,11 +1999,6 @@ ms@2.1.2, ms@^2.1.1:
2041 resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 1999 resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
2042 integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 2000 integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
2043 2001
2044 -mute-stream@0.0.8:
2045 - version "0.0.8"
2046 - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
2047 - integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==
2048 -
2049 natural-compare@^1.4.0: 2002 natural-compare@^1.4.0:
2050 version "1.4.0" 2003 version "1.4.0"
2051 resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" 2004 resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
...@@ -2213,13 +2166,6 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: ...@@ -2213,13 +2166,6 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0:
2213 dependencies: 2166 dependencies:
2214 wrappy "1" 2167 wrappy "1"
2215 2168
2216 -onetime@^5.1.0:
2217 - version "5.1.0"
2218 - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5"
2219 - integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==
2220 - dependencies:
2221 - mimic-fn "^2.1.0"
2222 -
2223 only@~0.0.2: 2169 only@~0.0.2:
2224 version "0.0.2" 2170 version "0.0.2"
2225 resolved "https://registry.yarnpkg.com/only/-/only-0.0.2.tgz#2afde84d03e50b9a8edc444e30610a70295edfb4" 2171 resolved "https://registry.yarnpkg.com/only/-/only-0.0.2.tgz#2afde84d03e50b9a8edc444e30610a70295edfb4"
...@@ -2247,7 +2193,7 @@ os-homedir@^1.0.0: ...@@ -2247,7 +2193,7 @@ os-homedir@^1.0.0:
2247 resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" 2193 resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
2248 integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= 2194 integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M=
2249 2195
2250 -os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: 2196 +os-tmpdir@^1.0.0:
2251 version "1.0.2" 2197 version "1.0.2"
2252 resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" 2198 resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
2253 integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= 2199 integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
...@@ -2553,14 +2499,6 @@ responselike@^1.0.2: ...@@ -2553,14 +2499,6 @@ responselike@^1.0.2:
2553 dependencies: 2499 dependencies:
2554 lowercase-keys "^1.0.0" 2500 lowercase-keys "^1.0.0"
2555 2501
2556 -restore-cursor@^3.1.0:
2557 - version "3.1.0"
2558 - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e"
2559 - integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==
2560 - dependencies:
2561 - onetime "^5.1.0"
2562 - signal-exit "^3.0.2"
2563 -
2564 retry@^0.8.0: 2502 retry@^0.8.0:
2565 version "0.8.0" 2503 version "0.8.0"
2566 resolved "https://registry.yarnpkg.com/retry/-/retry-0.8.0.tgz#2367628dc0edb247b1eab649dc53ac8628ac2d5f" 2504 resolved "https://registry.yarnpkg.com/retry/-/retry-0.8.0.tgz#2367628dc0edb247b1eab649dc53ac8628ac2d5f"
...@@ -2580,24 +2518,12 @@ rimraf@^2.6.1: ...@@ -2580,24 +2518,12 @@ rimraf@^2.6.1:
2580 dependencies: 2518 dependencies:
2581 glob "^7.1.3" 2519 glob "^7.1.3"
2582 2520
2583 -run-async@^2.4.0:
2584 - version "2.4.1"
2585 - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
2586 - integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==
2587 -
2588 -rxjs@^6.5.3:
2589 - version "6.5.5"
2590 - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.5.tgz#c5c884e3094c8cfee31bf27eb87e54ccfc87f9ec"
2591 - integrity sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==
2592 - dependencies:
2593 - tslib "^1.9.0"
2594 -
2595 safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: 2521 safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
2596 version "5.1.2" 2522 version "5.1.2"
2597 resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" 2523 resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
2598 integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== 2524 integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
2599 2525
2600 -safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: 2526 +safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0:
2601 version "5.2.1" 2527 version "5.2.1"
2602 resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 2528 resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
2603 integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 2529 integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
...@@ -2896,18 +2822,6 @@ text-table@^0.2.0: ...@@ -2896,18 +2822,6 @@ text-table@^0.2.0:
2896 resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" 2822 resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
2897 integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= 2823 integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=
2898 2824
2899 -through@^2.3.6:
2900 - version "2.3.8"
2901 - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
2902 - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
2903 -
2904 -tmp@^0.0.33:
2905 - version "0.0.33"
2906 - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
2907 - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
2908 - dependencies:
2909 - os-tmpdir "~1.0.2"
2910 -
2911 to-fast-properties@^2.0.0: 2825 to-fast-properties@^2.0.0:
2912 version "2.0.0" 2826 version "2.0.0"
2913 resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" 2827 resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
...@@ -2952,11 +2866,6 @@ tough-cookie@~2.5.0: ...@@ -2952,11 +2866,6 @@ tough-cookie@~2.5.0:
2952 psl "^1.1.28" 2866 psl "^1.1.28"
2953 punycode "^2.1.1" 2867 punycode "^2.1.1"
2954 2868
2955 -tslib@^1.9.0:
2956 - version "1.13.0"
2957 - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043"
2958 - integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==
2959 -
2960 tsscmp@1.0.6: 2869 tsscmp@1.0.6:
2961 version "1.0.6" 2870 version "1.0.6"
2962 resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.6.tgz#85b99583ac3589ec4bfef825b5000aa911d605eb" 2871 resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.6.tgz#85b99583ac3589ec4bfef825b5000aa911d605eb"
...@@ -2981,11 +2890,6 @@ type-check@^0.4.0, type-check@~0.4.0: ...@@ -2981,11 +2890,6 @@ type-check@^0.4.0, type-check@~0.4.0:
2981 dependencies: 2890 dependencies:
2982 prelude-ls "^1.2.1" 2891 prelude-ls "^1.2.1"
2983 2892
2984 -type-fest@^0.11.0:
2985 - version "0.11.0"
2986 - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1"
2987 - integrity sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==
2988 -
2989 type-fest@^0.8.1: 2893 type-fest@^0.8.1:
2990 version "0.8.1" 2894 version "0.8.1"
2991 resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" 2895 resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
......