├── MACOS_howto.md ├── README.md ├── assets ├── cy1.PNG ├── cy2.PNG ├── cy3.PNG ├── cy4.PNG ├── cy5.PNG ├── cy6.PNG ├── cy7.PNG └── cy8.png └── client.js /MACOS_howto.md: -------------------------------------------------------------------------------- 1 | # CY2ME 2 | 깔끔하고 안전하게 싸이월드 백업할 수 있는 방법을 공유한다. 3 | 일반적으로 싸이월드 백업을 프로그램화하게 되면 ID와 비밀번호를 검증되지 않은 프로그램에 입력해야 한다. 4 | 이는 백업을 하려는 사용자들로 하여금 불안함을 유발할 수 있는 원인이 된다. 5 | 본 방법은 따로 프로그램화하지 않고, 간단하게 브라우저만으로 백업할 수 있는 솔루션을 제공한다. 6 | 7 | * 다이어리, 공유 다이어리, 게시판, 사진첩, 블로그, 상태 메세지 백업 가능 8 | * 사진첩은 포스팅한 날짜를 기준으로 Google Photos나 안드로이드 갤러리 등의 사진첩에서 쉽게 관리 가능 9 | 10 | **본 페이지에서는 MAC OS에서의 방법을 설명드립니다.** 11 | * Windows 사용자는 아래 링크를 참조하세요. 12 | https://github.com/designe/cy2me 13 | * 문의 사항은 아래 링크에 댓글로 달아주세요. 14 | https://blog.jbear.co/post/cyworld_backup/ 15 | 16 | 17 | ## 필요한 도구 18 | - MAC OS : MAC OS 가 설치된 모든 PC에서 가능 19 | - Chrome Browser : Microsoft Edge, Firefox도 상관없음. 20 | 21 | 22 | ### 아래 순서를 잘 따라하면 쉽게 백업이 가능합니다. 23 | 24 | 25 | ## 1. 싸이월드 접속 26 | 27 | https://cy.cyworld.com/cyMain 28 | 싸이월드 계정을 까먹었을꺼다. 29 | 얼른 아이디/비밀번호부터 찾아서 로그인 30 | 31 | 32 | ## 2. 싸이월드에 홈피 접속 33 | ![cyworld2](https://github.com/designe/cy2me/blob/master/assets/cy2.PNG?raw=true) 34 | 35 | 백업을 하려면 예전의 미니홈피를 접속해야하는데 36 | 오른쪽 상단에 파란 동그라미 쳐놓은 프로필 이미지를 선택 37 | 38 | 39 | ## 3. Chrome Devtool 실행 40 | ![image](https://user-images.githubusercontent.com/1748714/71323798-9ce74100-251a-11ea-9bf7-afb6e926d6f3.png) 41 | 42 | 홈피 접속된 상태에서 F12를 눌러보자. 43 | Chrome Devtool 이라는게 실행된다. 이 툴은 dock처럼 페이지 바로 옆에 실행이 되거나 독립된 창으로 실행되는데 기본 세팅은 옆에 탭처럼 켜진다. (설정으로 바꿀 수 있음) 44 | 45 | 이제 거의 다 왔다. 46 | 47 | 48 | ## 4) Console 탭 선택 49 | 아래 스크립트를 세번 빠르게 클릭하면 전체 선택이 가능하다. 50 | Chrome Devtool의 Console Tab을 선택한 후 복사한 스크립트를 붙여넣고 엔터를 치면 된다. 51 | **2020/07/01 일자로 서버 불안정에 따른 502/504 Gateway 이슈가 자주 발생함에 따라** 52 | **백업 실패한 컨텐츠에 대해 최대 5회까지 재시도하는 코드가 반영되었습니다.** 53 | ```js 54 | var last_id,last_dt,tag_value,startdate,enddate,forder_id,airepageno,airecase,airelastdate;var html="";var type="more";var search="";var allMap={};var postIdx=0;var activateReply=true;if(type=="more"){last_id=$(".hiddenId:last").data("id");last_dt="";airepageno=$("#airepageno").val();airecase=$("#airecase").val();airelastdate=$("#airelastdate").val();srchType=$("#searchType").val();tag_value=$("#tagname").val();forder_id=$("#folderid").val()}else{home_idx=0}var backupStartTime=0;var backupEndTime=0;var CY2ME_CATEGORY_INFO={M:{type:"M",title:"Diary",backup_status:"#diary-backup-status"},O:{type:"O",title:"ShareDiary",backup_status:"#share-diary-backup-status"},1:{type:"1",title:"Board",backup_status:"#board-backup-status"},2:{type:"2",title:"Photo",backup_status:"#photo-backup-status"},B:{type:"B",title:"Blog",backup_status:"#blog-backup-status"},P:{type:"P",title:"After2015",backup_status:"#newcontent-backup-status"},T:{type:"T",title:"Status",backup_status:"#status-backup-status"}};function getBase64Image(img){var canvas=document.createElement("canvas");canvas.width=img.width;canvas.height=img.height;var ctx=canvas.getContext("2d");ctx.drawImage(img,0,0);var dataURL=canvas.toDataURL("image/jpg");return dataURL.replace(/^data:image\/(png|jpg);base64,/,"")}function printImageList(){var ret="";var imageCount=0;var allPosts=Object.values(allMap);for(var i=0;itotalFeedsCount?totalFeedsCount:startIdx+30}else{for(var key in allMap){if(allMap[key].isCompleted)continue;else{allMap[key].isStarted=false}}totalFeeds=Object.entries(allMap);startIdx=0;endIdx=30;tryCount++;if(tryCount>0&&tryCount<=5)console.log("CY2ME | 백업에 실패한 컨텐츠에 대하여 재시도합니다 | "+tryCount+"회 시도");else if(tryCount>5)finishTrigger=true}if(finishTrigger){clearInterval(intervalCtx);console.log("CY2ME | Backup is going to be finished after 15 seconds. | Thank you");setTimeout((function(){var backupTime=Date.now()-backupStartTime;console.log("총 "+backupTime/1e3+"초 동안 백업이 진행되었습니다.");console.log("Backup Finished.");var allPosts=Object.values(allMap);var file=new Blob([JSON.stringify(allPosts,null,1)],{type:"text/plain;charset=utf-8"});saveAs("MyCy"+typeFeed.title+"_"+Date().replace(/\ /gi,"_").split("_GMT")[0]+".txt",file);$(typeFeed.backup_status+" .lds-hourglass").css("display","none");$(typeFeed.backup_status+" .backup-message").css("display","inline-block")}),15e3)}else{var hitCal=successCnt/totalFeedsCount*100;console.log("Collecting Feed | "+(Date.now()-backupStartTime)+"ms | Eval "+tryCount+" startCnt = "+startCnt+" noStartCnt = "+noStartCnt+" successCnt = "+successCnt+" failCnt = "+failCnt+" | "+hitCal.toFixed(2)+"% ["+successCnt+" / "+totalFeedsCount+"] ")}}),1e4)}),300)}function collectShareDiaries(comment=true){collectFeeds("O",comment)}function collectBoards(comment=true){collectFeeds("1",comment)}function collectBlogs(comment=true){collectFeeds("B",comment)}function collectDiaries(comment=true){collectFeeds("M",comment)}function collectPhotos(comment=true){collectFeeds("2",comment)}function collect2015(comment=true){collectFeeds("P",comment)}function collectStatus(comment=true){collectFeeds("T",comment)}var connectCyPostCnt=0;function connectCyPost(id,post,time=0){try{var ajaxOption={url:"/home/"+homeTid+"/post/"+id+"/layer",cache:false,async:true,dataType:"html",data:{},beforeSend:function(){post.isStarted=true}};if(time!=0)ajaxOption["timeout"]=time;$.ajax(ajaxOption).done((function(viewResult){var output=$("").append($.parseHTML(viewResult));if(typeof $(".textData",output)[0]==="undefined"){post.isCompleted=false;allMap[id]=post;return false}if(post.type!="M"&&post.type!="O")post.title=$("#cyco-post-title",output)[0].innerText.trim();var content="";var imageObj=$("section .cyco-imagelet figure img",output);for(var i=0;i";var contentObj=$(".textData",output);for(var i=0;i30)postIdx=30;else return;do{readCyPost(totalCount-postIdx,t);postIdx+=30}while(totalCount-postIdx>0);console.log("Analyzation Finishd.")}function readCyPost(cnt,t){var ret=0;$.ajax({url:"/home/"+homeTid+"/posts",data:{startdate:startdate,enddate:enddate,folderid:"",tagname:tag_value,lastid:last_id,lastdate:last_dt,listsize:cnt,homeId:homeTid,airepageno:airepageno,airecase:airecase,airelastdate:airelastdate,searchType:srchType,search:search},cache:false,dataType:"json",async:false,success:function(data){last_dt=data.lastdate;ret=data.totalCount;var baseIdx=postIdx;if(data.postList.length>0){data.postList.some((function(value,index){if(t&&value.serviceType!=t)return;var post={id:value.identity,type:value.serviceType,writer:value.writer,viewCount:value.viewCount,commentCount:value.commentCount,isStarted:false};switch(post.type){case"2":post.image=value.summaryModel.image;break;case"1":break;case"P":break;case"T":break;case"M":break;case"O":break;case"B":break;case"7":return false}allMap[value.identity]=post;var cal=(baseIdx+index)/ret*100;console.log("Analyzing Feed | "+value.identity+" | "+cal.toFixed(2)+"% ["+(baseIdx+index)+" / "+ret+"] ")}))}else{ret=0}}});return ret}function initializeCy2me(){var css="";$(css).appendTo(document.head);$(".profile dfn:first").html("");var diaryBtn=$("").text("다이어리 백업").click(collectDiaries);var diaryStatus=$("
done
");var shareDiaryBtn=$("").text("공유 다이어리 백업").click(collectShareDiaries);var shareDiaryStatus=$("
done
");var boardBtn=$("").text("게시판 백업").click(collectBoards);var boardStatus=$("
done
");var blogBtn=$("").text("블로그 백업").click(collectBlogs);var blogStatus=$("
done
");var photoBtn=$("").text("사진첩 백업").click(collectPhotos);var photoStatus=$("
done
");var newContentBtn=$("").text("2015 이후 백업").click(collect2015);var newContentStatus=$("
done
");var statusBtn=$("").text("상태 메세지 백업").click(collectStatus);var statusStatus=$("
done
");$(".profile dfn:first").append(diaryBtn);$(".profile dfn:first").append(diaryStatus);$(".profile dfn:first").append($(""));$(".profile dfn:first").append(shareDiaryBtn);$(".profile dfn:first").append(shareDiaryStatus);$(".profile dfn:first").append($(""));$(".profile dfn:first").append(boardBtn);$(".profile dfn:first").append(boardStatus);$(".profile dfn:first").append($(""));$(".profile dfn:first").append(blogBtn);$(".profile dfn:first").append(blogStatus);$(".profile dfn:first").append($("
"));$(".profile dfn:first").append(photoBtn);$(".profile dfn:first").append(photoStatus);$(".profile dfn:first").append($(""));$(".profile dfn:first").append(newContentBtn);$(".profile dfn:first").append(newContentStatus);$(".profile dfn:first").append($(""));$(".profile dfn:first").append(statusBtn);$(".profile dfn:first").append(statusStatus);console.log("CY2ME : Cyworld 백업 준비 완료 | 웹페이지에 보시면 백업 메뉴가 활성화되어 있습니다.")}initializeCy2me(); 55 | ``` 56 | 57 | 백업 준비 완료되었다는 메세지가 뜰 것이다. 58 | ![cyworld8](https://github.com/designe/cy2me/blob/master/assets/cy8.png?raw=true) 59 | 60 | ## 5) 다이어리, 게시판, 블로그에 쓴 글 백업 61 | 홈피의 방문자 기록을 보면 아래와 같이 백업 메뉴가 활성화된 모습을 볼 수 있다. 62 | 63 | ![image](https://user-images.githubusercontent.com/1748714/71323608-6c9ea300-2518-11ea-9bfc-f3bcf518fdda.png) 64 | 65 | 남은 일은? 66 | 원하는 버튼을 누르기만 하면 된다 :) 67 | 68 | ![image](https://user-images.githubusercontent.com/1748714/71323712-a45a1a80-2519-11ea-966c-a1abb6b75fd4.png) 69 | 70 | 버튼을 누르면 위와 같이 콘솔창에는 현재 상태가 뜨고, Finish가 뜨면 자동으로 백업 파일이 다운로드 된다. 71 | MyCyDiary_현재시간.txt 파일로 저장이 되어 있다. 브라우저 다운로드 목록을 확인해보자. 72 | 73 | 74 | ## 5-1) 백업 파일 뷰어로 확인 75 | https://dev.jbear.co/cy2me 76 | 위 링크에 접속해 다운로드 받은 파일을 선택하면 깔끔하게 정리되어 확인할 수 있다. 77 | 78 | 다음은 사진 저장 방법이다. 79 | 이건 조금 어려우니 집중해서 따라하길 바란다. 80 | 81 | 82 | ## 6. 사진 전체 다운로드 방법 (MAC OS 에서의 사용법) 83 | 84 | 시작은 비슷하다. 사진첩 백업 버튼을 클릭해보자. 85 | 수집이 완료되면 MyCyPhotos_현재시간.txt가 다운로드된다. 86 | 일반적으로 MAC OS에서는 아래 위치에 저장될 것이다. 87 | ```bash 88 | ~/Downloads/MyCyPhotos_***.txt # 사용자 폴더의 Downloads 폴더내 저장 89 | ``` 90 | 91 | 이 파일을 https://dev.jbear.co/cy2me 에 접속해 로드한 후, 92 | "모든 사진 다운로드" 버튼을 누르면 또 다른 텍스트 파일이 받아진다. 93 | 94 | terminal 을 실행해보자. 95 | 우선 사진을 저장하고 싶은 폴더를 만든다. 96 | ```bash 97 | mkdir cyphotos 98 | ``` 99 | 만들어진 cyphotos라는 폴더에 다운로드 받은 MyCyPhotos_download_script_blah.txt 텍스트 파일을 이동시킨다. 100 | ```bash 101 | cd cyphotos 102 | mv ~/Downloads/MyCyPhotos_download_script_***.txt ./ 103 | ``` 104 | 105 | 마지막으로 아래의 명령어를 따라치면 싸이월드의 컨텐츠들이 컴퓨터에 저장이 된다. 106 | ![cyworld6](https://github.com/designe/cy2me/blob/master/assets/cy6.PNG?raw=true) 107 | ```bash 108 | awk '{print $1 " -O " $2}' MyCyPhotos_download_script_***.txt | xargs -n3 wget 109 | ``` 110 | wget이 없는 경우 위 명령어가 동작안할 수도 있는데, 111 | 그럴땐 아래와 같이 curl이라는 명령어로 대체해서 사용한다. 112 | ```bash 113 | awk '{print $1 " -O " $2}' MyCyPhotos_download_script_***.txt | xargs -n3 curl 114 | ``` 115 | 116 | 117 | **추가 팁 : 고급 Option** 118 | exiftool을 쓰면 사진 찍은 날짜를 포스팅 올린 날짜로 일괄 변경해준다. 119 | https://www.sno.phy.queensu.ca/~phil/exiftool/ 120 | 위 사이트에 접속하면 MAC용 exiftool을 받을 수 있고, 관리자 권한으로 실행하여 설치한다. 121 | 아래 명령어로 해당 이미지 폴더에서 실행하시면 끝! 122 | ![cyworld7](https://github.com/designe/cy2me/blob/master/assets/cy7.PNG?raw=true) 123 | ```bash 124 | exiftool "-AllDatestotalFeedsCount?totalFeedsCount:startIdx+30}else{for(var key in allMap){if(allMap[key].isCompleted)continue;else{allMap[key].isStarted=false}}totalFeeds=Object.entries(allMap);startIdx=0;endIdx=30;tryCount++;if(tryCount>0&&tryCount<=5)console.log("CY2ME | 백업에 실패한 컨텐츠에 대하여 재시도합니다 | "+tryCount+"회 시도");else if(tryCount>5)finishTrigger=true}if(finishTrigger){clearInterval(intervalCtx);console.log("CY2ME | Backup is going to be finished after 15 seconds. | Thank you");setTimeout((function(){var backupTime=Date.now()-backupStartTime;console.log("총 "+backupTime/1e3+"초 동안 백업이 진행되었습니다.");console.log("Backup Finished.");var allPosts=Object.values(allMap);var file=new Blob([JSON.stringify(allPosts,null,1)],{type:"text/plain;charset=utf-8"});saveAs("MyCy"+typeFeed.title+"_"+Date().replace(/\ /gi,"_").split("_GMT")[0]+".txt",file);$(typeFeed.backup_status+" .lds-hourglass").css("display","none");$(typeFeed.backup_status+" .backup-message").css("display","inline-block")}),15e3)}else{var hitCal=successCnt/totalFeedsCount*100;console.log("Collecting Feed | "+(Date.now()-backupStartTime)+"ms | Eval "+tryCount+" startCnt = "+startCnt+" noStartCnt = "+noStartCnt+" successCnt = "+successCnt+" failCnt = "+failCnt+" | "+hitCal.toFixed(2)+"% ["+successCnt+" / "+totalFeedsCount+"] ")}}),1e4)}),300)}function collectShareDiaries(comment=true){collectFeeds("O",comment)}function collectBoards(comment=true){collectFeeds("1",comment)}function collectBlogs(comment=true){collectFeeds("B",comment)}function collectDiaries(comment=true){collectFeeds("M",comment)}function collectPhotos(comment=true){collectFeeds("2",comment)}function collect2015(comment=true){collectFeeds("P",comment)}function collectStatus(comment=true){collectFeeds("T",comment)}var connectCyPostCnt=0;function connectCyPost(id,post,time=0){try{var ajaxOption={url:"/home/"+homeTid+"/post/"+id+"/layer",cache:false,async:true,dataType:"html",data:{},beforeSend:function(){post.isStarted=true}};if(time!=0)ajaxOption["timeout"]=time;$.ajax(ajaxOption).done((function(viewResult){var output=$("").append($.parseHTML(viewResult));if(typeof $(".textData",output)[0]==="undefined"){post.isCompleted=false;allMap[id]=post;return false}if(post.type!="M"&&post.type!="O")post.title=$("#cyco-post-title",output)[0].innerText.trim();var content="";var imageObj=$("section .cyco-imagelet figure img",output);for(var i=0;i";var contentObj=$(".textData",output);for(var i=0;i30)postIdx=30;else return;do{readCyPost(totalCount-postIdx,t);postIdx+=30}while(totalCount-postIdx>0);console.log("Analyzation Finishd.")}function readCyPost(cnt,t){var ret=0;$.ajax({url:"/home/"+homeTid+"/posts",data:{startdate:startdate,enddate:enddate,folderid:"",tagname:tag_value,lastid:last_id,lastdate:last_dt,listsize:cnt,homeId:homeTid,airepageno:airepageno,airecase:airecase,airelastdate:airelastdate,searchType:srchType,search:search},cache:false,dataType:"json",async:false,success:function(data){last_dt=data.lastdate;ret=data.totalCount;var baseIdx=postIdx;if(data.postList.length>0){data.postList.some((function(value,index){if(t&&value.serviceType!=t)return;var post={id:value.identity,type:value.serviceType,writer:value.writer,viewCount:value.viewCount,commentCount:value.commentCount,isStarted:false};switch(post.type){case"2":post.image=value.summaryModel.image;break;case"1":break;case"P":break;case"T":break;case"M":break;case"O":break;case"B":break;case"7":return false}allMap[value.identity]=post;var cal=(baseIdx+index)/ret*100;console.log("Analyzing Feed | "+value.identity+" | "+cal.toFixed(2)+"% ["+(baseIdx+index)+" / "+ret+"] ")}))}else{ret=0}}});return ret}function initializeCy2me(){var css="";$(css).appendTo(document.head);$(".profile dfn:first").html("");var diaryBtn=$("").text("다이어리 백업").click(collectDiaries);var diaryStatus=$("
done
");var shareDiaryBtn=$("").text("공유 다이어리 백업").click(collectShareDiaries);var shareDiaryStatus=$("
done
");var boardBtn=$("").text("게시판 백업").click(collectBoards);var boardStatus=$("
done
");var blogBtn=$("").text("블로그 백업").click(collectBlogs);var blogStatus=$("
done
");var photoBtn=$("").text("사진첩 백업").click(collectPhotos);var photoStatus=$("
done
");var newContentBtn=$("").text("2015 이후 백업").click(collect2015);var newContentStatus=$("
done
");var statusBtn=$("").text("상태 메세지 백업").click(collectStatus);var statusStatus=$("
done
");$(".profile dfn:first").append(diaryBtn);$(".profile dfn:first").append(diaryStatus);$(".profile dfn:first").append($(""));$(".profile dfn:first").append(shareDiaryBtn);$(".profile dfn:first").append(shareDiaryStatus);$(".profile dfn:first").append($(""));$(".profile dfn:first").append(boardBtn);$(".profile dfn:first").append(boardStatus);$(".profile dfn:first").append($(""));$(".profile dfn:first").append(blogBtn);$(".profile dfn:first").append(blogStatus);$(".profile dfn:first").append($("
"));$(".profile dfn:first").append(photoBtn);$(".profile dfn:first").append(photoStatus);$(".profile dfn:first").append($(""));$(".profile dfn:first").append(newContentBtn);$(".profile dfn:first").append(newContentStatus);$(".profile dfn:first").append($(""));$(".profile dfn:first").append(statusBtn);$(".profile dfn:first").append(statusStatus);console.log("CY2ME : Cyworld 백업 준비 완료 | 웹페이지에 보시면 백업 메뉴가 활성화되어 있습니다.")}initializeCy2me(); 54 | ``` 55 | 56 | 아래와 같이 백업 준비 완료되었다는 메세지가 뜰 것이다. 57 | ![cyworld8](https://github.com/designe/cy2me/blob/master/assets/cy8.png?raw=true) 58 | 59 | 60 | ## 5) 다이어리, 게시판, 블로그에 쓴 글 백업 61 | 홈피의 방문자 기록을 보면 아래와 같이 백업 메뉴가 활성화된 모습을 볼 수 있다. 62 | 63 | ![image](https://user-images.githubusercontent.com/1748714/71323608-6c9ea300-2518-11ea-9bfc-f3bcf518fdda.png) 64 | 65 | 남은 일은? 66 | 원하는 버튼을 누르기만 하면 된다 :) 67 | 68 | ![image](https://user-images.githubusercontent.com/1748714/71323712-a45a1a80-2519-11ea-966c-a1abb6b75fd4.png) 69 | 70 | 버튼을 누르면 위와 같이 콘솔창에는 현재 상태가 뜨고, Finish가 뜨면 자동으로 백업 파일이 다운로드 된다. 71 | MyCyDiary_현재시간.txt 파일로 저장이 되어 있다. 브라우저 다운로드 목록을 확인해보자. 72 | 73 | 74 | ## 5-1) 백업 파일 뷰어로 확인 75 | https://dev.jbear.co/cy2me 76 | 위 링크에 접속해 다운로드 받은 파일을 선택하면 깔끔하게 정리되어 확인할 수 있다. 77 | 78 | 다음은 사진 저장 방법이다. 79 | 이건 조금 어려우니 집중해서 따라하길 바란다. 80 | 81 | 82 | ## 6) 사진 전체 다운로드 방법 (Windows에서의 사용법) 83 | 84 | 시작은 비슷하다. 사진첩 백업 버튼을 클릭해보자. 85 | 수집이 완료되면 MyCyPhotos_현재시간.txt가 다운로드된다. 86 | https://dev.jbear.co/cy2me 에 접속해 이 파일을 로드한 후, 87 | "모든 사진 다운로드" 버튼을 눌러서 다운로드용 스크립트를 받는다. 88 | 89 | 이걸 복사해서 사용자 폴더(일반적으로 C:\Users\사용자이름 )에 저장해보자. 90 | 91 | 그리고 Powershell 이라는걸 실행해야 한다. 92 | ![cyworld4](https://github.com/designe/cy2me/blob/master/assets/cy4.PNG?raw=true) 93 | Win + R 을 누르면 실행창이 뜨고, 여기다가 powershell을 누르면 실행된다. 94 | 모르겠으면 시작 누르고 찾다보면 나온다. 95 | 96 | ![cyworld5](https://github.com/designe/cy2me/blob/master/assets/cy5.PNG?raw=true) 97 | ```bash 98 | Get-Content .\MyCyPhotos_download_script_현재시간.txt | %{ Invoke-WebRequest $_.split(" ")[0] -OutFile $_.split(" ")[1];} 99 | ``` 100 | 101 | 위에 명령어 치면 막 다운로드 받아지는게 느껴진다. 102 | 103 | **추가 팁 : 고급 Option** 104 | exiftool을 쓰면 사진 찍은 날짜를 포스팅 올린 날짜로 일괄 변경해준다. 105 | https://www.sno.phy.queensu.ca/~phil/exiftool/ 106 | Windows는 여기서 다운로드받아서 설치하고 powershell이나 cmd에서 사용하면 된다. 107 | 아래 명령어로 해당 이미지 폴더에서 실행하시면 끝! 108 | 109 | ```bash 110 | exiftool "-AllDates totalFeedsCount) ? totalFeedsCount : startIdx + 30; 134 | } else { 135 | for(var key in allMap) { 136 | if(allMap[key].isCompleted) 137 | continue; 138 | else { 139 | allMap[key].isStarted = false; 140 | } 141 | } 142 | 143 | totalFeeds = Object.entries(allMap); 144 | 145 | startIdx = 0; 146 | endIdx = 30; 147 | tryCount++; 148 | 149 | if(tryCount > 0 && tryCount <= 5) 150 | console.log("CY2ME | 백업에 실패한 컨텐츠에 대하여 재시도합니다 | " + tryCount + "회 시도" ); 151 | else if(tryCount > 5) 152 | finishTrigger = true; 153 | } 154 | 155 | if(finishTrigger) { 156 | clearInterval(intervalCtx); 157 | console.log("CY2ME | Backup is going to be finished after 15 seconds. | Thank you"); 158 | setTimeout(function() { 159 | var backupTime = Date.now() - backupStartTime; 160 | console.log("총 " + (backupTime / 1000.0) + "초 동안 백업이 진행되었습니다."); 161 | console.log("Backup Finished."); 162 | var allPosts = Object.values(allMap); 163 | var file = new Blob([JSON.stringify(allPosts, null, 1)], {type: "text/plain;charset=utf-8"}); 164 | saveAs("MyCy" + typeFeed.title +"_" + Date().replace(/\ /gi, "_").split("_GMT")[0] + ".txt", file); 165 | $(typeFeed.backup_status + " .lds-hourglass").css("display", "none"); 166 | $(typeFeed.backup_status + " .backup-message").css("display", "inline-block"); 167 | }, 15000); 168 | } else { 169 | var hitCal = (successCnt / totalFeedsCount) * 100.0; 170 | console.log("Collecting Feed | " + (Date.now() - backupStartTime) + "ms | Eval " + tryCount + " startCnt = " + startCnt + " noStartCnt = " + noStartCnt + " successCnt = " + successCnt + " failCnt = " + failCnt + " | " + hitCal.toFixed(2) + "% [" + successCnt + " / " + totalFeedsCount + "] " ); 171 | } 172 | }, 10000); 173 | }, 300); 174 | } 175 | 176 | function collectShareDiaries(comment=true) { collectFeeds("O", comment); } 177 | function collectBoards(comment=true) { collectFeeds("1", comment); } 178 | function collectBlogs(comment=true) { collectFeeds("B", comment); } 179 | function collectDiaries(comment=true) { collectFeeds("M", comment); } 180 | function collectPhotos(comment=true) { collectFeeds("2", comment); } 181 | function collect2015(comment=true) { collectFeeds("P", comment); } 182 | function collectStatus(comment=true) { collectFeeds("T", comment); } 183 | 184 | var connectCyPostCnt = 0; 185 | function connectCyPost(id, post, time=0) { 186 | 187 | try { 188 | var ajaxOption = { 189 | url: "/home/" + homeTid + "/post/"+ id + "/layer", 190 | cache:false, 191 | async:true, 192 | dataType:'html', 193 | data:{}, 194 | beforeSend: function() { 195 | post.isStarted = true; 196 | } 197 | }; 198 | 199 | if(time != 0) 200 | ajaxOption["timeout"] = time; 201 | 202 | $.ajax(ajaxOption).done(function(viewResult) { 203 | var output = $("").append($.parseHTML(viewResult)); 204 | if(typeof $(".textData", output)[0] === 'undefined'){ 205 | post.isCompleted = false; 206 | allMap[id] = post; 207 | return false; 208 | } 209 | 210 | if(post.type != "M" && post.type != "O") 211 | post.title = $("#cyco-post-title", output)[0].innerText.trim(); 212 | var content = ""; 213 | var imageObj = $("section .cyco-imagelet figure img", output); 214 | for(var i = 0; i < imageObj.length; i++) 215 | content += ""; 216 | var contentObj = $(".textData", output); 217 | for(var i = 0; i < contentObj.length; i++) 218 | content += contentObj[i].innerHTML.trim(); 219 | post.content = content; 220 | post.date = $(".view1", output)[0].innerText.trim().split(" ")[0].split('\t').pop(); 221 | post.time = $(".view1", output)[0].innerText.trim().split(" ")[1]; 222 | post.isCompleted = true; 223 | if(activateReply) { 224 | var commentCount = post.commentCount; 225 | if(commentCount != 0){ 226 | $.ajax({ 227 | url: "/home/" + homeTid + "/post/" + id + "/comment", 228 | dataType:'json', 229 | async:true, 230 | data: {}, 231 | }).done(function(comments) { 232 | post.comments = []; 233 | for(comment_idx in comments.commentList) { 234 | var temp = comments.commentList[comment_idx].contentModel[0]; 235 | temp.name = comments.commentList[comment_idx].writer.name; 236 | if(typeof temp.name === 'undefined'){ 237 | temp.name = comments.commentList[comment_idx].writer.nickname; 238 | } 239 | post.comments.push(temp); 240 | } 241 | allMap[id] = post; 242 | }).fail(function() { 243 | console.log(id + " | Failed | 댓글 수집에 실패하였습니다. 댓글을 제외한 컨텐츠만 저장됩니다."); 244 | allMap[id] = post; 245 | }); 246 | } else { 247 | allMap[id] = post; 248 | } 249 | } else { 250 | allMap[id] = post; 251 | } 252 | }).fail(function(request, status ,error){ 253 | //console.log(id + " | Failed | 컨텐츠 수집 시간이 초과되었습니다."); 254 | post.isCompleted = false; 255 | allMap[id] = post; 256 | }); 257 | } 258 | catch(e) { 259 | console.error(e); 260 | console.log("try catch error : " + e); 261 | //allMap[id] = post; 262 | } 263 | } 264 | 265 | function readAllCyPosts(t) { 266 | // initialize global variables 267 | allMap = {}; 268 | postIdx = 0; 269 | last_dt = null; 270 | var totalCount = readCyPost(30, t); 271 | postIdx = totalCount; 272 | 273 | if(totalCount > 30) postIdx = 30; 274 | else return; 275 | 276 | do { 277 | readCyPost(totalCount - postIdx, t); 278 | postIdx += 30; 279 | } while (totalCount - postIdx > 0); 280 | console.log("Analyzation Finishd."); 281 | } 282 | 283 | function readCyPost(cnt, t) { 284 | var ret = 0; 285 | $.ajax({ 286 | url: '/home/'+ homeTid + "/posts", 287 | data:{ 288 | "startdate" : startdate, 289 | "enddate" : enddate, 290 | "folderid" : "", 291 | "tagname" : tag_value, 292 | "lastid" : last_id, 293 | "lastdate" : last_dt, 294 | "listsize" : cnt, 295 | "homeId" : homeTid, 296 | "airepageno" : airepageno, 297 | "airecase" : airecase, 298 | "airelastdate" : airelastdate, 299 | "searchType" : srchType, 300 | "search" : search 301 | }, 302 | cache: false, 303 | dataType: "json", 304 | async:false, 305 | success: function(data) { 306 | last_dt = data.lastdate; 307 | ret = data.totalCount; 308 | var baseIdx = postIdx; 309 | 310 | if(data.postList.length > 0) { 311 | data.postList.some(function(value, index) { 312 | //for(value in data.postList) { 313 | if(t && value.serviceType != t) 314 | return; 315 | 316 | var post = { 317 | "id" : value.identity, 318 | "type" : value.serviceType, 319 | "writer" : value.writer, 320 | "viewCount" : value.viewCount, 321 | "commentCount" : value.commentCount, 322 | "isStarted" : false 323 | }; 324 | 325 | switch(post.type) { 326 | case "2": /* include images */ 327 | post.image = value.summaryModel.image; 328 | break; 329 | case "1": /* Board */ 330 | break; 331 | case "P": /* 2015 */ 332 | break; 333 | case "T": /* Intro */ 334 | break; 335 | case "M": /* Diary */ 336 | break; 337 | case "O": /* Share Diary */ 338 | break; 339 | case "B": /* Blog */ 340 | break; 341 | case "7": 342 | //if(t) allPosts[baseIdx + index] = post; 343 | //else allPosts.push(post); 344 | return false; 345 | } 346 | 347 | allMap[value.identity] = post; 348 | 349 | var cal = ((baseIdx + index) / ret ) * 100; 350 | console.log("Analyzing Feed | " + value.identity + " | " + cal.toFixed(2) + "% [" + (baseIdx + index) + " / " + ret + "] " ); 351 | }); 352 | }else { 353 | ret = 0; 354 | } 355 | } 356 | }); 357 | return ret; 358 | } 359 | 360 | function initializeCy2me() { 361 | 362 | var css = '"; 369 | $(css).appendTo(document.head); 370 | 371 | $(".profile dfn:first").html(""); 372 | var diaryBtn = $("").text("다이어리 백업").click(collectDiaries); 373 | var diaryStatus = $("
done
"); 374 | var shareDiaryBtn = $("").text("공유 다이어리 백업").click(collectShareDiaries); 375 | var shareDiaryStatus = $("
done
"); 376 | var boardBtn = $("").text("게시판 백업").click(collectBoards); 377 | var boardStatus = $("
done
"); 378 | var blogBtn = $("").text("블로그 백업").click(collectBlogs); 379 | var blogStatus = $("
done
"); 380 | var photoBtn = $("").text("사진첩 백업").click(collectPhotos); 381 | var photoStatus = $("
done
"); 382 | var newContentBtn = $("").text("2015 이후 백업").click(collect2015); 383 | var newContentStatus = $("
done
"); 384 | var statusBtn = $("").text("상태 메세지 백업").click(collectStatus); 385 | var statusStatus = $("
done
"); 386 | 387 | $(".profile dfn:first").append(diaryBtn); 388 | $(".profile dfn:first").append(diaryStatus); 389 | $(".profile dfn:first").append($("")); 390 | $(".profile dfn:first").append(shareDiaryBtn); 391 | $(".profile dfn:first").append(shareDiaryStatus); 392 | $(".profile dfn:first").append($("")); 393 | $(".profile dfn:first").append(boardBtn); 394 | $(".profile dfn:first").append(boardStatus); 395 | $(".profile dfn:first").append($("")); 396 | $(".profile dfn:first").append(blogBtn); 397 | $(".profile dfn:first").append(blogStatus); 398 | $(".profile dfn:first").append($("
")); 399 | $(".profile dfn:first").append(photoBtn); 400 | $(".profile dfn:first").append(photoStatus); 401 | $(".profile dfn:first").append($("")); 402 | $(".profile dfn:first").append(newContentBtn); 403 | $(".profile dfn:first").append(newContentStatus); 404 | $(".profile dfn:first").append($("")); 405 | $(".profile dfn:first").append(statusBtn); 406 | $(".profile dfn:first").append(statusStatus); 407 | 408 | console.log("CY2ME : Cyworld 백업 준비 완료 | 웹페이지에 보시면 백업 메뉴가 활성화되어 있습니다."); 409 | } 410 | 411 | initializeCy2me(); 412 | --------------------------------------------------------------------------------