IT/잡다구리

카카오톡 채팅방 카카오봇 , 배터리 ,날씨, 뉴스 등등 가져오기

월공 2020. 8. 29. 00:13
728x90
300x250

2020.09.04 내용추가

현재 카카오톡 오픈채팅방에 팬다 Jr. 라는 카카오 오픈채팅 공식 봇이 추가됐네요 !

아래는 팬다를 이용한 방식이 아닌것을 미리 참고해주세요 ~!

 

팬다를 이용한 방식이 아니지만 아래와같이 개발을 해놓으면 팬다를 이용하여 매일매일 점심때 메뉴가 나오게 할수도 있고, 아침마다 날씨를 나오게도 할수 있겠죠 !


 

요즘 퇴근하고 심심해서 찔끔찔끔 자바스크립트 수정해서 만지는 카카오봇이 있습니다.

물론 제가 처음부터 만들진않았고 , 어느.. 고수분께서 만들어놓은 앱을 이용하여

 

거기 안에서 js 를 수정해서 사용하는 방식인데요

운영하고있는 오픈채팅방이 있어서 , 갖가지 기능을 넣고 유용하게 잘 사용하고 있습니다.

새로운 인원이 왔을때 // 만 쳐도 환영글 및 공지 참고해달라는 말을 내보낸다거나, 혹은 공지 내용 일부를 보낸다던가..

점심, 저녁 을 쳤을때 메뉴를 추천해준다던가, 

/로또 라고 쳤을때 로또번호를 내준다던가 기타 등등 뭐 그런것들이요

 


 

카카오봇 초기세팅은 아래 링크에 너무나도 깔끔하게 잘 정리해놓으신 분의 글이 있어서 첨부하겠습니다

https://sompunch.tistory.com/29

 

0.카카오톡 오픈채팅 봇 만드는 방법

카카오톡 오픈채팅봇 만들기 오픈채팅봇 하는방법을 물어보셔서 남겨봅니다. 서브폰으로 사용하실분들은 우선 카카오톡 아이디를 개설하셔야 합니다. 서브폰도 번호가 있다면 바로 개설이 되�

sompunch.tistory.com

간단하게 워밍업 JS 입니다

아래 JS 는 보기만해도 뭐하는 내용인지 충분히 이해가 가시지요?

response 라는 함수 내부 안에 들어가야합니다.

톡방이름은 당연히 똑같아야하구요

 

sender 가 보내는 이의 이름이라서 이름만 맞춰주면 그사람이 하는말에만 반응하게도 맞출수있습니다

function response(room, msg, sender, isGroupChat, replier, imageDB, packageName) {

   if (room == "톡방이름") {
      msg = msg.trim();
      msg = msg.replace(/ /g, "");

      if (msg == "내이름") {
          replier.reply(sender + " 입니다.");
      }

      if (msg == "니이름") {
          replier.reply("bot");
      }

      if(sender == "월공"){
        if(msg=="/개발테스트"){
            replier.reply(room + " || " + msg  + " || " + sender  + " || " + isGroupChat + " || " + replier + " || " + imageDB + " || " + packageName);
        }
      }

}

//아래 4개의 메소드는 액티비티 화면을 수정할때 사용됩니다.
function onCreate(savedInstanceState, activity) {
   var textView = new android.widget.TextView(activity);
   textView.setText("Hello, World!");
   textView.setTextColor(android.graphics.Color.DKGRAY);
   activity.setContentView(textView);
}

function onStart(activity) { }
function onResume(activity) { }
function onPause(activity) { }
function onStop(activity) { }

아래 JS 는 환영문구 및 디스코드 안내 , 식사 메뉴 추천, 네이버 검색 , 번역 ,로또 ,봇 배터리 현황 , 날씨, 현재상영영화 안내 입니다 당연히  response 안에서 돌려야하구요

날씨 호출시

식사 메뉴 추천, 로또, 배터리, 날씨는 다른 곳에서 퍼왔어서 그대로 올려놓습니다 ~

영화 같은경우에는 현재상영영화를 평점순으로 네이버에서 긁어오는데 내용이 워낙 .. 길어서 저건 소스 짜놓고

톡방 인원들이 내용이 너무 길다고 대화 가린다고 싫어해서 잘 쓰진않는 호출입니다 .. ㅎㅎ

그리고 수정해야될 부분도 있구요.

혹시라도 필요하신분이 있으실까봐 첨부해놓습니다

영화 호출시
로또 호출시

if (msg == "//" || msg == "@@" || msg == ".." || msg.indexOf("/어서오세요") != -1 || msg.indexOf("/환영") != -1 || msg.indexOf("/안녕하세요") != -1 || msg.indexOf(".어서오세요") != -1 || msg.indexOf(".환영") != -1 || msg.indexOf(".안녕하세요") != -1) {
         replier.reply("어서오세요 공지사항 봐주세요.");
      } else if (msg.indexOf("/디스코드") != -1 || msg.indexOf("/디코") != -1 || msg.indexOf("/discord") != -1 || msg.indexOf(".디스코드") != -1 || msg.indexOf(".디코") != -1 || msg.indexOf(".discord") != -1) {
         replier.reply("https://discord.gg/ㅇㅇㅇㅇㅇ \n입장하시면 됩니다");

      } else if (msg.trim() == "점심" || msg.trim() == "저녁") {
         var list = ["청국장찌개", "순두부찌개", "고추장찌개", "부대찌개", "김치찌개", "된장찌개", "비지찌개", "전찌개", "동태찌개", "갈비찜", "닭볶음탕", "스테이크", "아귀찜", "삼계탕", "수육", "월날쌈", "불고기", "찜닭", "제육덮밥", "비빔밥", "오므라이스", "카레덮밥", "김치볶음밥", "오징어덮밥", "짜장밥", "야채볶음밥", "간장밥", "육개장", "떡국", "미역국", "콩나물국", "북엇국", "소고기무국", "시래깃국", "된장국", "감잣국", "튀김", "소시지야채볶음", "골뱅이소면", "부침개", "어묵탕", "닭똥집볶음", "순대볶음", "토스트", "또띠아", "떡꼬치", "쿠키", "떡볶이", "호떡", "샌드위치", "시리얼", "팝시클", "라면", "토마토스파게티", "크림스파게티", "봉골레스파게티", "잔치국수", "비빔국수", "칼국수", "우동", "볶음우동", "콩국수", "전복죽", "추어탕", "장어구이", "낙지연포탕", "갈비탕", "훈제오리", "닭죽", "삼계탕", "더덕구이", "오니기리", "캘리포니아롤", "스시", "유부초밥", "밥버거", "스팸", "볶음밥", "투움바파스타", "김밥", "알로하김밥", "호두크림치즈김밥", "바나나쉐이크", "닭가슴살샐러드", "리코타치즈", "단호박스프", "양배추스프", "두부스테이크", "연어덮밥", "오차즈케", "불고기브리또", "샐러드파스타", "크로크무슈", "몬테크리스토", "팬케이크", "치킨마요덮밥", "오믈렛", "프렌치토스트", "조개스프", "에그베네딕트", "만둣국", "떡국", "라자냐", "칠리새우", "잡채", "누룽지", "고추장찌개", "포테이토피자", "냉채라면", "짜파구리", "진라면", "달걀", "야채볶음", "프리타타", "계란말이", "계란찜", "스카치에그", "스터프드에그", "깐풍기", "탕수육", "두루치기", "제육볶음", "동파육", "중국집볶음밥", "잡채밥", "짬뽕밥", "짬뽕", "삼선짜장", "삼선짬뽕", "쟁반짜장", "닭갈비", "치킨까스", "돈까스", "치즈돈까스", "고구마치즈돈까스", "주먹밥", "리조또", "크로켓", "덴푸라", "가츠동", "하이라이스", "오코노미야끼", "미소시루", "우동", "규동", "라멘", "마파두부", "고추잡채", "곱창", "막창", "대창", "해물파전", "파전", "쌈밥", "칼국수", "수제비", "팥죽", "그라탕", "뇨끼", "나폴리피자", "페투치니알프레도", "파니니", "팟타이", "카오팟", "나시고랭", "쌀국수", "연유라떼", "분짜", "짜조", "반미(바게트샌드위치)", "허머스", "팔라펠", "케밥", "삭슈카", "페투쉬", "필라프", "쿠스쿠스", "피타", "무사카", "맥앤치즈", "클램차우더", "핫도그", "햄버거", "불고기버거", "빅맥", "상하이버거", "미트로프", "후라이드치킨", "양념치킨", "간장치킨", "닭강정", "잠발라야", "바비큐", "라타투이", "프렌치토스트", "뵈프부르기뇽", "뱅쇼", "크로크무슈", "마카롱", "부야베스", "끼슈", "코코뱅", "가리가리군", "가리비", "거북알", "거북이", "고드름", "구구콘", "깐도리", "꽃게랑", "누가바", "대롱대롱", "더블비얀코", "더위사냥", "돼지바", "마카롱아이스바", "말랑카우", "메로나", "바밤바", "보석바", "부라보콘", "붕어싸만코", "비비빅", "빅바", "빙빙바", "빠삐코", "빵또아", "빵빠레", "뽕따", "설레임", "셀렉션", "슈퍼콘", "쌍쌍바", "아맛나", "아시나요", "아이스파인", "엑설런트", "엔초", "요맘때", "옥메와까", "옥동자", "메가톤바", "와일드바디", "까마쿤", "와(아이스크림)", "와삭바", "울퉁불퉁", "월드콘", "조안나", "죠크박", "죠스바", "스크류바", "수박바", "쮸쮸바", "찬호박", "찰떡아이스", "캔디바", "쿠앤크", "쿠키오", "탱크보이", "테트리스", "토끼", "투게더", "티코", "폴라포", "하겐다즈", "호두마루", "홈런볼 아이스", "하겐다즈", "레드망고", "나뚜루", "구스띠모", "베스킨라빈스31", "롯데리아", "맥도날드", "치즈버거", "버거킹", "족발", "백숙", "삼겹살", "보쌈", "육회", "육사시미", "육회비빔밥", "순대", "홍어회", "물회", "굴비", "매운탕", "북엇국", "해물찜", "오징어볶음", "아귀찜", "골뱅이무침", "빈대떡", "호박전", "육전", "동래파전", "수제비", "떡국", "떡만둣국", "시래기국", "선지국", "순댓국", "소머리국밥", "콩나물국밥", "화채", "토란국", "재첩국", "곰탕", "닭곰탕", "설렁탕", "연포탕", "닭도리탕", "고기국수", "막국수", "비빔국수", "김치말이국수", "칼국수", "초계국수", "도토리묵", "밀면", "냉면", "찹쌀도넛", "회오리감자", "너비아니", "뒷고기", "전복죽", "야채죽"];
         var rannum = Math.floor(Math.random() * list.length);
         replier.reply(list[rannum]);
      } else if (msg.indexOf("/검색") != -1) {                  
         var search = msg.split("/검색");
         replier.reply("https://m.search.naver.com/search.naver?&sm=mtp_hty.top&where=m&query="+ search[1]);
      }else if (msg.indexOf("/번역") != -1) {
          var k_pattern = /^[가-힣]+$/;
          var e_pattern = /^[a-zA-Z]+$/;
          var pattern_num = /[0-9]/;        
          var pattern_spc = /[~!@#$%^&*()_+|<>?:{}]/;                  
          var papago = msg.split("/번역");

         if(k_pattern.test(papago[1]) || pattern_num.test(papago[1]) || pattern_spc.test(papago[1])){
            papago_result = Api.papagoTranslate("ko","en",papago[1]);
         }else{
            papago_result = Api.papagoTranslate("en","ko",papago[1]);
         }
         replier.reply(papago_result);

      }else if (msg.indexOf("/일번역") != -1) {
                  
         var papago_j = msg.split("/일번역");
         var papago_result_j = Api.papagoTranslate("ko","ja",papago_j[1]);
         replier.reply(papago_result_j);

      }else if (msg.indexOf("/로또") != -1) {
                  
       fir = new Array(45);
       sec = new Array(6);
        for (i = 0; i < 45; i++) fir[i] = i + 1;
        for (i = 0; i < 6; i++) {
           ran = parseInt(Math.random() * fir.length);
           sec[i] = fir[ran];
           fir.splice(ran,1);
           for (h = fir.length; h; h -= 1) {
              j = Math.floor(Math.random() * h);
              x = fir[h - 1];
              fir[h - 1] = fir[j];
              fir[j] = x;
           }
        }

        for (i = 0; i < 6; i++) {
           for (j = 0; j <= i; j++) {
              if(sec[i] <= sec[j]) {
                 k = sec[i];
                 sec[i] = sec[j];
                 sec[j] = k;
              }
           }
        }

        replier.reply(sec);


      } else if (msg.trim() == "/배터리") {
         var fill = ["알수없음", "충전중", "충전중 아님", "충전완료 후 충전중 아님", "충전 완료"];
         var ifilter = new android.content.IntentFilter(android.content.Intent.ACTION_BATTERY_CHANGED);
         var batteryStatus = Api.getContext().registerReceiver(null, ifilter);
         var battery = batteryStatus.getIntExtra(android.os.BatteryManager.EXTRA_STATUS, -1);
         var voltage = batteryStatus.getIntExtra(android.os.BatteryManager.EXTRA_VOLTAGE, -1);
         var level = batteryStatus.getIntExtra(android.os.BatteryManager.EXTRA_LEVEL, -1);
         var scale = batteryStatus.getIntExtra(android.os.BatteryManager.EXTRA_SCALE, -1);
         var am = Api.getContext().getSystemService(Api.getContext().ACTIVITY_SERVICE);
         var mem = new android.app.ActivityManager.MemoryInfo();
         am.getMemoryInfo(mem);
         var temp = batteryStatus.getIntExtra(android.os.BatteryManager.EXTRA_TEMPERATURE, -1);
         var ms1 = java.lang.System.currentTimeMillis();
         var ms2 = java.lang.System.currentTimeMillis();
         var ps = (((ms2 - ms1) / 1000) + "초");
         replier.reply("전원 : 켜짐\n현재상태 : " + fill[battery - 1] + "\n램 : " + (mem.availMem / mem.totalMem * 100).toFixed(2) + "% 남음\n배터리 : " + Math.round(level / scale * 100) + "%\n온도 : " + Math.round(temp) / 10 + "°C\n전압 : " + voltage + "mv");

      } else if (msg.trim() == "/날씨" || msg.trim() == ".날씨") {
         var data = Utils.getWebText("https://m.search.naver.com/search.naver?query=날씨");
         var data2 = data.split("전국날씨</strong>");
         var data3 = data2[1].split("특보");
         var data4 = data3[0].replace(/(<([^>]+)>)/g, "");
         data4 = data4.trim();
         data4 = data4.replace(/  /g, "\n");
         data4 = data4.replace(/도씨/g, "℃");
         data4 = data4.replace(/ /g, "");
         data4 = data4.substring(0, data4.indexOf("단위", 0));
         data4 = data4.trim();
         replier.reply("[현재 날씨]\n" + data4);
         
      } else if (msg.trim() == "/영화" || msg.trim() == ".영화") {
         var mdata = Utils.getWebText("https://m.search.naver.com/search.naver?where=m&sm=mtb_etc&query=현재상영영화");
         var mdata2 = mdata.split('<div class="card_content">');
         var mdata3 = mdata2[1].split('<div class="cm_error_no_result');
         var mdata4 = mdata3[0].replace(/(<([^>]+)>)/g, "");
         mdata4 = mdata4.trim();
         mdata4 = mdata4.replace(/평점/g, "★");
         mdata4 = mdata4.replace(/\n/g, "");
         mdata4 = mdata4.replace(/                                                                                                                        /g, "");
         mdata4 = mdata4.replace(/ /g, "");
         mdata4 = mdata4.replace(/개봉/g, "\n개봉 ");
         mdata4 = mdata4.replace(/출연/g, "\n출연 ");
         mdata4 = mdata4.replace(/예매하기예고편/g, "\n💙");
         replier.reply(mdata4);
      }

그리고 오늘 추가적으로 손을 봤던 부분은 일일뉴스 인데요

MoYa 글로벌 뉴스레터 라고해서 , 주요뉴스가 매일매일 올라오는 아주 고마운 사이트 입니다.

 

아래 링크에서 구독신청도 하실수 있으니 참고하시구요 ~!
https://www.wisetranslate.net/moya/global_news/newsletter/2020-08-28

 

MoYa 글로벌 뉴스레터

월마트, 틱톡 인수전 가세...MS와 협력 추진

www.wisetranslate.net

 

위 뉴스들의 타이틀과 상세링크를 긁어오고 싶었습니다

일단 이부분은 , 자바스크립트만으로 작업하기엔 제 실력으론 한계치도 있을뿐더러 소스가 너무 길어져서
(카카오봇 앱 자체에서 js 길이를 200줄 이상 인식하지않게 되있는거같더라구요 너무 길면 짤립니다 !)

 

제 개인 리눅스서버가 있어서 거기서 PHP 언어를 이용하여 먼저 위 링크에서 데이터를 뽑아주었습니다.

저처럼 노는 서버가 있으시다면 도메인 연결해서 데이터 가공해서 가져오시는것도 괜찮을듯 합니다

위 링크를 아래 처럼 뽑아오게 하는게 제 목표였습니다 :)

PHP 스누피 라이브러리를 이용하여 html 내용을 받아와서 데이터를 가공하여 배열에 담았습니다

아래 PHP 소스 참고하시기 바랍니다.

<?
	require($_SERVER['DOCUMENT_ROOT'].'/crawling/lib/Snoopy.class.php');	

	//$today = date("Y-m-d",strtotime("+1 days"));	
	$today = date("Y-m-d");	

	$newsUrl = 'https://www.wisetranslate.net/moya/global_news/newsletter/'.$today;
	 
	$snoopy = new Snoopy;

	$snoopy -> fetch($newsUrl);
	
	$title="";

	$html=$snoopy->results; 

	$dataCheck = preg_replace("(\<(/?[^\>]+)\>)", "", $html); 	  

	if(strpos($dataCheck, "No newsletter found on") !== false){
		echo "아직뉴스가없어요";
		exit;
	}else{	

		$html = explode("<strong>".$today."</strong>",$html);

		//윗대가리 자르고
		$html = $html[1];

		//아래 자르고
		$html = explode('class="es-footer"',$html);

		$html = $html[0];

		$title_tag="/\<h4 style=\".+\"\>(.*)\<\/h4\>/";
		preg_match_all($title_tag,$html,$title);	

		//var_dump($title[0]);
		
		preg_match_all('/<td class="es-m-p0r es-m-p20b" width="278" valign="top" align="center" style="padding:0;Margin:0;">(.*?)<\/table>/is', $html, $text);

		$news = Array();
		foreach ($text[1] as $link){
		  //echo $link;
		  preg_match_all("/<a[^>]* href=(['|\"]*)([^\\1\040>]*)\\1[^>]*>/is", $link, $result);

		  foreach ($result as $tag){
			  //echo $link;
			  $news_link = preg_replace("(\<(/?[^\>]+)\>)", "", $tag); 	  
			  //$news_link = array_filter($news_link);

			}		
		  $news[] = $news_link;
		}

	?>

	<?=$today?>
	<?	
	foreach ($title[0] as $k => $title){			
		$title = preg_replace("(\<(/?[^\>]+)\>)", "", $title); 	  
	?>
	<br>◎ <?=$title?><br><br><?=$news[$k][0]?>
	<?
		}

	}
?>

아래는 카카오봇 내부에 들어가는 JS 문입니다

 else if (msg.trim() == "/뉴스" || msg.trim() == ".뉴스") {

  var news = Utils.getWebText("크롤링 해준 URL");
  lastNews = news.replace(/(<([^>]+)>)/g, "");
  lastNews = lastNews.trim();         
  lastNews = lastNews.replace(/ /g, "");
  lastNews = lastNews.replace(/◎/g, "\n◎ ");   
  
  replier.reply(lastNews);
}

 

뉴스 호출시

 

참고로 저는 모비젠을 이용해서 작업했습니다 ~!

컴퓨터에서 소스치고 모비젠 이용해서 적용하고 했어요

더 좋은 방법이 있다면 공유좀 부탁드릴게요 ~!

 

728x90
300x250