LMSDownloader 제작기

우리 학교에서 새로운 이러닝 시스템을 도입했는데, 리액트 구버전을 사용했으나 조잡한 느낌이 없지 않아 있다고 생각했다. 옛날 이러닝은 기존에 쓰던 비디오 다운로더 크롬 확장 프로그램을 통해 강의를 다운받을 수 있었는데, 새로운 이러닝은 강의를 기괴한(?) 방식으로 보여주고 있어서 다른 다운로드 프로그램들이 잡아내지를 못했다.

capture_program

완성한 프로그램의 디자인.
아이콘은 단국대학교 공식 UI에서 가져왔다.

블로그에서는 일부 중요한 코드만 언급하고, 모든 코드는 Github에 공개되어 있고, 기여할 수 있다.

로직 구성하기

사이트 소스를 보니 그럴만도 했다. iframe이 4중으로 되어 있고, 마지막 강의가 들어있는 프레임은 contentDocument() 메소드가 차단되어 있어 가져오지를 못했다.

조금 더 생각을 바꾸고, 세번째 프레임까지 들어간 다음, 네번째 프레임을 띄워주고 거기서 video 객체의 src 경로를 가져올 수 있겠다 싶었다.

영상의 경로를 가져올 때 까지

우선 세번째 프레임까지는 contentDocument를 통해 들어갈 수 있어서 안의 컨텐츠 내용을 가져올 수 있다.

1
2
3
4
5
6
7
8
9
10
// 첫번째 강의의 경우
document
.getElementsByTagName("iframe")[1]
.contentDocument.getElementsByTagName("iframe")[0]
.contentDocument.getElementsByTagName("iframe")[0].src;
// 두번째 강의의 경우
document
.getElementsByTagName("iframe")[1]
.contentDocument.getElementsByTagName("iframe")[1]
.contentDocument.getElementsByTagName("iframe")[0].src;

코드가 바보같을 수도 있지만 우리 학교 이러닝에만 잘 사용되면 되므로 이 코드가 최적이라고 생각했다.

프로그램이 거의 완성되고 나서 알게된 건데, 2개 강의를 하루에 올려서 한 페이지에 영상이 2개가 로드되는 경우도 있었다. 그래서 스캔 버튼을 2개로 나누기로 하고 2번째 강의까지 성공적으로 src를 가져올 수 있었다.

다운로드만 하면 된다

기본적으로 클라이언트 사이드에서는 로컬이 아닌 주소의 다운로드 요청이 차단되어서 서버 사이드에서의 작업이 요구된다. 하지만 크롬 프로그램이기 때문에 chrome.downloads.download()를 사용할 수 있다는 정보를 찾았고 background.jspopup.js 두개로 나눠서 작업했다.

1
2
3
4
chrome.runtime.sendMessage({
action: "download",
source: vidUrl[0],
});

popup.js에서 위와 같은 메시지를 요청하면,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
chrome.runtime.onMessage.addListener((request) => {
if (request.action === "download") {
if (request.source.includes("dankook.commonscdn")) {
try {
chrome.downloads.download({
url: request.source,
});
} catch (err) {
alert(`오류: ${err.message}`);
}
} else {
alert("다운받을 수 있는 강의컨텐츠가 아닙니다😭");
}
}
});

background.js에서는 위와 같이 download 요청인지 검사 후 단국대에서 들어오는 요청인지 검사 후 다운로드를 시작한다. 다양한 경우가 있을 수 있으므로 에러 핸들링에 신경을 썼다.

마치며

일주일 중 하루는 내가 원하는 것을 하는 날로 살기로 했는데 5시간동안의 몰두 끝에 그럴듯하게 완성하니 하루를 잘 보낸 것 같다. (5시간 중 2시간은 구글링을 한 것 같다) 학교 사람들이 써준다면 정말 뿌듯할 것 같고, 안 쓰신다 해도 지인들이나 나는 유용하게 쓸 것 같다.