반응형

개인 봇 개발용으로 상업적 용도로 사용하는것이 아님을 밝힙니다.

이미지 퍼다가 돈버는 용도로 쓰셔서 걸리면 제 책임 아닙니다 ㅠ

네지레
타마키

캐릭터들 이미지 출력하기용

반응형

'이미지 > 무료 개발용 이미지' 카테고리의 다른 글

나히아 카봇 개발용 이미지  (0) 2022.02.25
반응형

개인 봇 개발용으로 캡쳐한 이미지로 카카오링크로 이미지 띄우기 테스트를 하기 위해 쓰고 있습니다. 상업적 용도로 쓰시다가 걸리시면 책임 못집니다~

No.1히어로

 

극열 폭염

 

네즈교장

 

로디

 

리커버리 걸
매드 테이프

 

머스타드
모우라 나가마사
문 피시
베로스

 

붕어빵가속

 

스나이프
신린카무이
엑토플라즘
영혼대화자

 

우츠시미 케미

 

전투의 주먹
진흙빌런

 

최후의 날
프레젠트 마이크
핑키

 

화려한 등장
시데로
록 탐정
흡혈과 사랑

반응형

'이미지 > 무료 개발용 이미지' 카테고리의 다른 글

개인 나히아 봇개발용  (0) 2022.02.27
반응형

구글 캘린더 api 데이터를 가져오기를 하기위해 열심히 서칭하여 구글 라이브러리를 호출하여 사용하는 샘플들을 사용하였으나, 내 프로젝트에서는 이상하게도 라이브러리를 사용하면 에러만 발생되어 js로 url 호출하는 방식으로 로그인부터 다시 만들게 되었다. OAuth 설정하는 부분은 https://sizin.tistory.com/105 이곳을 참고하면 될것같다.

 

js부분에 아래와 같이 GoogleLogin()이라는 함수를 만들었다.

function GoogleLogin() {
    	var url = "https://accounts.google.com/o/oauth2/auth?" +
		"client_id=12345abcde.apps.googleusercontent.com&" +
		"redirect_uri=http://localhost:8080/redirect.do&" +
		"response_type=code&" +
		"scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar.events%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar.readonly&" +
		"approval_prompt=force&" +
		"access_type=offline";
    	window.open(url, "self");
    }

GoogleLogin() 함수에서 client_id 값에 https://console.cloud.google.com/ 에서 등록된 OAuth 2.0 클라이언트 ID의

클라이언트 ID 값을 복사하여 넣고 redirect_uri는 로그인 된 후 호출하는 페이지로,

아래 캡쳐처럼 OAuth 2.0 클라이언트에서 승인된 리디렉션 URI에 호출할 컨트롤러명을 넣고 저장한다.

구글 Oauth에서 로그인 후 호출할 페이지 설정

CalendarController.java / redirect.do 구현

@RequestMapping(value="/redirect.do", method=RequestMethod.GET, produces=APPLICATION_JSON)
	public @ResponseBody void redirect(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
		String code = request.getParameter("code");
		System.out.println("code값 : " + code);
		String query = "code=" + code;
		query += "&client_id=" + "1234abcde.apps.googleusercontent.com";
		query += "&client_secret=" + "시크릿키";
		query += "&redirect_uri=" + "http://localhost:8080/redirect.do";
		query += "&grant_type=authorization_code";
		String tokenJson = postHttpConnection("https://accounts.google.com/o/oauth2/token", query);
		System.out.println("jsondata값 : " + tokenJson.toString());
		
		Gson gson = new Gson();
		Token token = gson.fromJson(tokenJson, Token.class); //vo로 저장
		Map<String, Object> regiToken = new HashMap<String, Object>();
		regiToken.put("acToken", token.getAccess_token());
		regiToken.put("rfToken", token.getRefresh_token());
		calendarService.updateCalToken(setToken);
	}

구글 Oauth 클라이언트 ID와 시크릿키

post 요청 메서드

private String postHttpConnection(String uri, String param) throws ServletException, IOException {
		URL url = new URL(uri);
		HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
		conn.setRequestMethod("POST");
		conn.setDoOutput(true);
		try (OutputStream stream = conn.getOutputStream()) {
			try (BufferedWriter wd = new BufferedWriter(new OutputStreamWriter(stream))) {
				wd.write(param);
			}
		}
		int responseCode = conn.getResponseCode();
		System.out.println(responseCode);
		String line;
		StringBuffer buffer = new StringBuffer();
		try (InputStream stream = conn.getInputStream()) {
			try (BufferedReader rd = new BufferedReader(new InputStreamReader(stream))) {
				while ((line = rd.readLine()) != null) {
					buffer.append(line);
					buffer.append('\r');
				}
			}
		} catch (Throwable e) {
			//e.printStackTrace();
			return Integer.toString(responseCode);
		}
		return buffer.toString();
	}

Token.java

@Getter
@Setter
@Alias("Token")
public class Token {
	private String access_token;
	private int expires_in;
	private String refresh_token;
	private String scope;
	private String token_type;
	private String id_token;
}

컨트롤러와 토큰vo 추가 후 구글로그인 함수를 호출하게 되면

로그인이 완료 된 후 access_token 값과 refresh_token 값을 map형태로 CalendarService로 DB에 저장하게 된다.

서비스 부분은 mybatis를 사용하여 로컬DB와 연동되게 직접 만들면 된다.

 

refresh_token은 access_token 값이 만료된 경우 access_token을 다시 구글쪽에 요청하여 받아오는 역할을 한다.

 

refresh_token으로 access_token을 재요청하여 DB에 저장하는 소스

String query = "client_id=" + "1245abcdef.apps.googleusercontent.com";
	query += "&client_secret=" + "시크릿 키값";
	query += "&refresh_token=" + "DB에 저장된 리플레시 토큰값";
	query += "&grant_type=" + "refresh_token";
String tokenJson = postHttpConnection("https://oauth2.googleapis.com/token", query);
Gson gson = new Gson();
Token token = gson.fromJson(tokenJson, Token.class);
Map<String, Object> updateToken = new HashMap<String, Object>();
updateToken.put("acToken", token.getAccess_token());
calendarService.updateCalToken(updateToken);

구글 캘린더에서 일정을 가져오기 전에 먼저 어떤 캘린더에서 가져와야 하므로

캘린더 목록을 호출하여 선택 하는 과정을 거쳐야 한다. 

 

DB에서 가져온 엑세스 토큰으로 GET요청을 하는 과정

String ac_Token = calendarService.getCalToken();
String returnJson = getHttpConnection("https://www.googleapis.com/calendar/v3/users/me/calendarList?access_token=" + ac_Token);
if(returnJson.equals("401") || returnJson.equals("404")){ //토큰 만료시 에러 발생
	throw new NullPointerException();
}

JSONObject jObject;
jObject = new JSONObject(returnJson);
Map<String, Object> addData;
List<Object> addDataList = new ArrayList<Object>();
JSONArray jArray = jObject.getJSONArray("items");
for(int i = 0; i < jArray.length();i++){
	addData = new HashMap<String, Object>();
	jObject = jArray.getJSONObject(i);
	addData.put("id", jObject.getString("id"));
	addData.put("summary", jObject.getString("summary"));
	addDataList.add(addData);
}
result.put("list", addDataList);

필자는 json파싱된 캘린더의 고유 id값과 제목을 리스트에 담아서 프론트쪽에 리턴하여 사용하였다.

id값과 제목을 콤보박스로 선택하여 값을 넘기는 js는 생략하겠다. 

 

토큰을 받아서 GET요청을 하는 메서드

private String getHttpConnection(String uri, String token) throws ServletException, IOException {
		URL url = new URL(uri);
		HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
		conn.setRequestMethod("GET");
		conn.setRequestProperty("Authorization", "Bearer " + token);
		conn.setRequestProperty("Accept", "application/json");	 
		int responseCode = conn.getResponseCode();
		String line;
		StringBuffer buffer = new StringBuffer();
		try (InputStream stream = conn.getInputStream()) {
			try (BufferedReader rd = new BufferedReader(new InputStreamReader(stream, "UTF-8"))) {
				while ((line = rd.readLine()) != null) {
					buffer.append(line);
					buffer.append('\r');
				}
			}
		} catch (Throwable e) {
			//e.printStackTrace();
			return Integer.toString(responseCode);
		}
		return buffer.toString();
	}

HttpsURLConnection의 setRequestProperty() 함수로 헤더에 베어러 토큰값을 넣어주는게 핵심이다.

 

콤보박스에 캘린더 목록들을 넣는 js

var selectBox = $("select[name='calendarList']");
    	$.ajax({
            type: "POST",
            url: "/GetCalendarList.do",
    		async : false,
    		contentType : false,
    		processData : false, 
    		dataType : "json",
            success: function (res) {
            	console.log("return map data = " + JSON.stringify(res.list));
            	$.each(res.list, function(idx, val) {
    	        selectBox.append("<option value=" + val.id + ">" + val.summary + "</option>");
    	        //console.log("id값 : " + val.id + "/ 캘린더 이름 : " + val.summary);
    	        });
             }
        });

js까지 만들어서 호출하게 되면 화면단의 calendarList라는 콤보박스에 캘린더 목록들이 들어가는걸 확인할 수 있다.

 

이제 동작안하는 구글 라이브러리 없이 캘린더 id값으로 캘린더에 일정 내보내기, 가져오기 등을 사용할 수 있게 되었다.

반응형
반응형

<script src="https://uicdn.toast.com/tui.date-picker/latest/tui-date-picker.js"></script> 

토스트의 tui.date-picker 캘린더를 사용하기위해 cdn으로 호출하여 사용하다가

인터넷이 막힌 서버에 업로드하기 위해 cdn주소로 소스를 복사하여 로컬에 넣어서 테스트를 했으나

요일 부분 한글이 깨지는 현상이 발생하였다. 처음에는 인코딩 문제인줄알고 이클립스에서 utf-8로 바꿀수있는 모든 부분을 수정하고 파일도 utf-8 인코딩하여 저장하는 뻘짓을 하다가 tui-date-picker.js를 확인해보니 깨진 한글 부분이 있었다. 그래서 해당 부분을 아래처럼 한글로 바꿔서 수정하니 정상적으로 한글이 표기 되었다.

ko: {
    titles: {
      DD: ['일요일', '월요일', '화요일', '수요일', '목요일', '금요일', '토요일'],
      D: ['일', '월', '화', '수', '목', '금', '토'],
      MMM: ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월'],
      MMMM: ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월']
    },
    titleFormat: 'yyyy.MM',
    todayFormat: 'To\\d\\ay: yyyy.MM.dd (D)',
    date: '날짜',
    time: '시간'
  }

cdn을 웹주소로 호출하게 되면 한글이 깨지는건 생각도 못했던 것이다.

개발자는 언제나 뻘짓에서 뻘짓으로 끝나는 느낌이다.

반응형
반응형

Github에서 FormUpload 소스를 사용하다가 동일한 키값으로 파일을 동시 전송해야하는데 해당기능이 개발되지 않아서 소스를 뜯어 고쳐 보았다.

사용법은 아래와 같다.

FormUpload multiForm = new FormUpload();
multiForm.Key = "AES 32자리 키값";
multiForm.AddStringParam(false, "stringdatakey", "value"); //AddStringParam()의 첫번째 매개변수는 AES암호화 여부
multiForm.AddFileParam(fasle, "files", FilePath); //files키값의 파일 첨부 (같은키값 사용가능)
Dictionary<string, string> jsonResult = multiForm.SendPage(ipaddress); //json형식 데이터를 리턴
string result = jsonResult.ContainsKey("Data") ? jsonResult["Data"] : ""; //Data라는 키값의 데이터가 존재할때 result값에 해당값 대입

같은 키값이 되도록 수정한 부분은 2중 foreach문을 사용하여 list에 저장된 값이 전송되도록 하였다.

FormUpload 클래스만 사용하면 Post통신할때 아주 간편해졌다.

FormUpload.cs
0.02MB
AES.cs
0.01MB

 

반응형

'개발언어 > C#' 카테고리의 다른 글

C# OCX DLL 못찾는 오류  (0) 2020.12.03
c# TCP 파일 전송 프로그램  (1) 2020.02.28
c# 영상처리 중 렉걸릴 때  (0) 2020.02.26
SetupApiDll.dll dll 못 찾는 오류  (0) 2020.02.26
OpenCvSharp 셋업 프로젝트 오류  (0) 2020.02.12
반응형

잘되던 프로그램이 갑자기 "클래스가 등록되지 않았습니다. (예외가 발생한 HRESULT: 0x80040154..." 라는 오류와 함께 실행이 되지 않았다.

프로젝트내 참조를 확인해보니 OCX dll들이 노란빛의 느낌표가 있던것을 확인하였다.

2~3일동안 별짓을 다하다가 결국 해결방안을 찾았다.

프로젝트 참조에 에러표시가 있던 dll들을 삭제시킨 후 OCX를 C:\Windows\SysWOW64 폴더에 넣고

콘솔(cmd)을 관리자 권한으로 실행하여 regsvr32명령으로 해당 OCX를 레지스트리에 등록 해준다.

다음으로 Visual Studio에서

디자이너 모드 -> 도구 상자 -> 우클릭 -> 항목선택 -> COM -> 해당 OCX를 찾아서 선택하고

컨트롤을 디자이너 아무곳이나 추가하게 되면 참조에 자동으로 C#에서 사용가능한 DLL(Ax...)로 변환되어 사용 가능하게 되었다.

반응형

'개발언어 > C#' 카테고리의 다른 글

C# Http 파일 전송  (0) 2020.12.04
c# TCP 파일 전송 프로그램  (1) 2020.02.28
c# 영상처리 중 렉걸릴 때  (0) 2020.02.26
SetupApiDll.dll dll 못 찾는 오류  (0) 2020.02.26
OpenCvSharp 셋업 프로젝트 오류  (0) 2020.02.12
반응형

주요 소스 정리

Tcp 소켓 오픈 소스

private void TcpSocketOpen()
        {
            try
            {
                receiveSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 2020);          //2020포트의 서버를 연다.
                receiveSocket.Bind(endPoint);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

Tcp 소켓 연결 소스

private void TcpSocketConnect()
        {
            if (conCheck) return; //연결 되어 있으면 재연결 안함
            try
            {
                sendSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                sendSocket.Connect(IPAddress.Parse(textBox1.Text), 2020);  //2020포트의 서버에 연결
                //sendSocket.ReceiveTimeout = 5000;
                conCheck = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                button2.Enabled = false;
            }
        }

Tcp 소켓 수신 대기 소스

private void Listen()
        {
            if (listenCheck) return;  //연결 되어 있으면 재연결 안함
            try
            {
                receiveSocket.Listen(20);
                receiveSocket = receiveSocket.Accept();

                listenThread = new Thread(Receive_Data);   //실제 통신을 담당하는 쓰레드 생성
                listenThread.Start();
                listenCheck = true;
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message);
                button3.Enabled = true;
                if(listenCheck)
                    listenCheck = false;
            }
        }

RTP헤더는 추가하지 않았고

파일 이름 사이즈, 파일 이름, 파일 크기 <- 헤더로 사용하고

파일 내용물이 맨 뒤에 붙게 만들었다.

클라이언트 하나로 송수신이 가능하게 만들었고 같은 네트워크 대역대에 있는 컴퓨터만 연결 가능하다.

서버를 사용하면 데몬을 통해 송수신하면 될 것 같다.

FileTranfer.zip
0.22MB

내가 직접 만든거라 바이러스는 절대 없음.

반응형

'개발언어 > C#' 카테고리의 다른 글

C# Http 파일 전송  (0) 2020.12.04
C# OCX DLL 못찾는 오류  (0) 2020.12.03
c# 영상처리 중 렉걸릴 때  (0) 2020.02.26
SetupApiDll.dll dll 못 찾는 오류  (0) 2020.02.26
OpenCvSharp 셋업 프로젝트 오류  (0) 2020.02.12
반응형

https://babysunmoon.tistory.com/entry/visual-studio-installer-Uninstall-%EC%B6%94%EA%B0%80%ED%95%98%EA%B8%B0

 

visual studio installer Uninstall 추가하기

이건 너무 잊어버릴것 같아서 적는다... 이거 먼저; visual sutdio 배포 및 설치파일 만들기 시 Uninstall 파일 같이 추가 하기. 파일시스템 창에서 우클릭, 시스템 폴더를 추가 한다. 시스템 폴더 선택 후 파일..

babysunmoon.tistory.com

파일시스템 창에서 우클릭, 시스템 폴더를 추가 한다.

시스템 폴더 선택 후 파일 추가 하기 클릭

파일은 C:\Windows\System32\msiexec.exe 

msiexec.exe 파일을 선택 후 우측 속성창에서 속성을 변경
 - Condition = Not Installed (직접입력)

 - Permanent = True

 - System = True
 - Transitive = True
 - Vital = False

그리고 해당 파일이 생성될 위치로 가서 바로가기를 만들고

지금 진행중인 setup 프로젝트를 클릭하면 속성창에 ProductCode 가 아래 그림과 같이 나오는데 복사 해놓고

바로가기 속성창에다가

/x {product code}  를 입력하면된다.

반응형

+ Recent posts