import { addEvent, getElement, isOneOf, removeEvent } from '../util'
import { emptyCleanups, KakaoError, processRules, UA } from '../common'
import { makeCustomLink, makeDefaultLink, makeScrapLink } from './linkGenerator'
import { capitalize } from './common'
import webSender from './webSender'
import talkSender from './talkSender'
import rules from './rules'
/**
* 메시지에서 콘텐츠 영역이나 버튼 클릭 시에 이동되는 링크 정보 오브젝트입니다. 오브젝트 내 프로퍼티 중 하나 이상은 반드시 존재해야 합니다.
* @alias LinkObject
* @typedef {Object} LinkObject
* @property {String} [webUrl] PC버전 카카오톡에서 사용하는 웹 링크 URL
* @property {String} [mobileWebUrl] 모바일 카카오톡에서 사용하는 웹 링크 URL
* @property {String} [androidExecParams] 안드로이드 카카오톡에서 사용하는 앱 링크 URL에 사용될 파라미터
* @property {String} [iosExecParams] iOS 카카오톡에서 사용하는 앱 링크 URL에 사용될 파라미터
* @memberof Kakao.Link
*/
/**
* 콘텐츠의 내용을 담고 있는 오브젝트입니다.
* @alias ContentObject
* @typedef {Object} ContentObject
* @property {String} title 콘텐츠의 타이틀
* @property {String} imageUrl 콘텐츠의 이미지 URL
* @property {LinkObject} link 콘텐츠 클릭 시 이동할 링크 정보
* @property {Number} [imageWidth] 콘텐츠의 이미지 너비 (단위: 픽셀)
* @property {Number} [imageHeight] 콘텐츠의 이미지 높이 (단위: 픽셀)
* @property {String} [description] 콘텐츠의 상세 설명
* @memberof Kakao.Link
*/
/**
* 좋아요 수, 댓글 수 등의 소셜 정보를 표현하기 위해 사용되는 오브젝트입니다.
* @alias SocialObject
* @typedef {Object} SocialObject
* @property {Number} [likeCount] 콘텐츠의 좋아요 수
* @property {Number} [commentCount] 콘텐츠의 댓글 수
* @property {Number} [sharedCount] 콘텐츠의 공유 수
* @property {Number} [viewCount] 콘텐츠의 조회 수
* @property {Number} [subscriberCount] 콘텐츠의 구독 수
* @memberof Kakao.Link
*/
/**
* 메시지 하단에 추가되는 버튼 오브젝트입니다.
* @alias ButtonObject
* @typedef {Object} ButtonObject
* @property {String} title 버튼의 타이틀
* @property {LinkObject} link 버튼 클릭 시 이동할 링크 정보
* @memberof Kakao.Link
*/
/**
* 가격 정보를 표현하기 위해 사용되는 오브젝트입니다.
* @alias CommerceObject
* @typedef {Object} CommerceObject
* @property {Number} regularPrice 정상가격
* @property {Number} [discountPrice] 할인된 가격
* @property {Number} [discountRate] 할인율
* @property {Number} [fixedDiscountPrice] 정액 할인 가격, 할인율과 동시 사용불가
* @memberof Kakao.Link
*/
/**
* @alias DefaultFeedSettings
* @typedef {Object} DefaultFeedSettings
* @property {String} objectType 고정값 "feed"
* @property {ContentObject} content 메인 콘텐츠
* @property {SocialObject} [social] 소셜 정보
* @property {String} [buttonTitle] 버튼명, [앱 설정]에 따른 기본 링크 사용, buttonTitle과 buttons 함께 있을 경우 buttons가 적용됨
* @property {ButtonObject[]} [buttons] 버튼, 링크 설정 가능, buttonTitle과 buttons 함께 있을 경우 buttons가 적용됨
* @property {Boolean} [installTalk=false] 카카오톡이 설치되어 있지 않은 경우 마켓의 카카오톡 설치 페이지로 이동합니다.
* @property {Function} [callback] 카카오링크 웹공유에서 공유 버튼 클릭 시 호출되는 콜백 함수 (IE 제외)
* @property {Object|String} [serverCallbackArgs] 카카오링크 공유 시 전송되는 링크 콜백에 포함되는 파라미터. [링크 콜백 가이드로 이동](https://developers.kakao.com/docs/latest/ko/message/js#set-kakaolink-callback)
* @memberof Kakao.Link
*/
/**
* @alias DefaultListSettings
* @typedef {Object} DefaultListSettings
* @property {String} objectType 고정값 "list"
* @property {String} headerTitle 헤더 타이틀
* @property {LinkObject} headerLink 헤더 링크
* @property {ContentObject[]} contents 메인 콘텐츠
* @property {String} [buttonTitle] 버튼명, [앱 설정]에 따른 기본 링크 사용, buttonTitle과 buttons 함께 있을 경우 buttons가 적용됨
* @property {ButtonObject[]} [buttons] 버튼, 링크 설정 가능, buttonTitle과 buttons 함께 있을 경우 buttons가 적용됨
* @property {Boolean} [installTalk=false] 카카오톡이 설치되어 있지 않은 경우 마켓의 카카오톡 설치 페이지로 이동합니다.
* @property {Function} [callback] 카카오링크 웹공유에서 공유 버튼 클릭 시 호출되는 콜백 함수 (IE 제외)
* @property {Object|String} [serverCallbackArgs] 카카오링크 공유 시 전송되는 링크 콜백에 포함되는 파라미터. [링크 콜백 가이드로 이동](https://developers.kakao.com/docs/latest/ko/message/js#set-kakaolink-callback)
* @memberof Kakao.Link
*/
/**
* @alias DefaultLocationSettings
* @typedef {Object} DefaultLocationSettings
* @property {String} objectType 고정값 "location"
* @property {ContentObject} content 메인 콘텐츠
* @property {String} address 지도 뷰에서 사용 할 주소, ex.성남시 분당구 판교역로 235
* @property {String} [addressTitle] 지도 뷰에서 사용될 주소명, ex.카카오 본사
* @property {SocialObject} [social] 소셜 정보
* @property {String} [buttonTitle] 버튼명, [앱 설정]에 따른 기본 링크 사용, buttonTitle과 buttons 함께 있을 경우 buttons가 적용됨
* @property {ButtonObject[]} [buttons] 버튼, 링크 설정 가능, buttonTitle과 buttons 함께 있을 경우 buttons가 적용됨
* @property {Boolean} [installTalk=false] 카카오톡이 설치되어 있지 않은 경우 마켓의 카카오톡 설치 페이지로 이동합니다.
* @property {Function} [callback] 카카오링크 웹공유에서 공유 버튼 클릭 시 호출되는 콜백 함수 (IE 제외)
* @property {Object|String} [serverCallbackArgs] 카카오링크 공유 시 전송되는 링크 콜백에 포함되는 파라미터. [링크 콜백 가이드로 이동](https://developers.kakao.com/docs/latest/ko/message/js#set-kakaolink-callback)
* @memberof Kakao.Link
*/
/**
* @alias DefaultCommerceSettings
* @typedef {Object} DefaultCommerceSettings
* @property {String} objectType 고정값 "commerce"
* @property {ContentObject} content 메인 콘텐츠
* @property {CommerceObject} commerce 가격 정보
* @property {String} [buttonTitle] 버튼명, [앱 설정]에 따른 기본 링크 사용, buttonTitle과 buttons 함께 있을 경우 buttons가 적용됨
* @property {ButtonObject[]} [buttons] 버튼, 링크 설정 가능, buttonTitle과 buttons 함께 있을 경우 buttons가 적용됨
* @property {Boolean} [installTalk=false] 카카오톡이 설치되어 있지 않은 경우 마켓의 카카오톡 설치 페이지로 이동합니다.
* @property {Function} [callback] 카카오링크 웹공유에서 공유 버튼 클릭 시 호출되는 콜백 함수 (IE 제외)
* @property {Object|String} [serverCallbackArgs] 카카오링크 공유 시 전송되는 링크 콜백에 포함되는 파라미터. [링크 콜백 가이드로 이동](https://developers.kakao.com/docs/latest/ko/message/js#set-kakaolink-callback)
* @memberof Kakao.Link
*/
/**
* @alias DefaultTextSettings
* @typedef {Object} DefaultTextSettings
* @property {String} objectType 고정값 "text"
* @property {String} text 최대 200자의 텍스트
* @property {String} [buttonTitle] 버튼명, [앱 설정]에 따른 기본 링크 사용, buttonTitle과 buttons 함께 있을 경우 buttons가 적용됨
* @property {ButtonObject[]} [buttons] 버튼, 링크 설정 가능, buttonTitle과 buttons 함께 있을 경우 buttons가 적용됨
* @property {Boolean} [installTalk=false] 카카오톡이 설치되어 있지 않은 경우 마켓의 카카오톡 설치 페이지로 이동합니다.
* @property {Function} [callback] 카카오링크 웹공유에서 공유 버튼 클릭 시 호출되는 콜백 함수 (IE 제외)
* @property {Object|String} [serverCallbackArgs] 카카오링크 공유 시 전송되는 링크 콜백에 포함되는 파라미터. [링크 콜백 가이드로 이동](https://developers.kakao.com/docs/latest/ko/message/js#set-kakaolink-callback)
* @memberof Kakao.Link
*/
/**
* 링크 타입 (Feed, List, Location, Commerce, Text)에 맞는 Object를 구성하여 링크를 쉽게 전송할 수 있습니다.
* @function createDefaultButton
* @param {DefaultFeedSettings|DefaultListSettings|DefaultLocationSettings|DefaultCommerceSettings|DefaultTextSettings} settings 카카오링크와 관련된 설정을 key/value로 전달합니다.
* @param {String|HTMLElement} settings.container DOM Element 또는 Element의 ID Selector를 넘기면, 해당 Element를 클릭할 때 카카오링크가 전송됩니다.
* @see {@link Kakao.Link.sendDefault} 직접 카카오링크 버튼을 제작하여 사용할 때 이용하세요.
* @see {@link https://developers.kakao.com/tool/demo/message/kakaolink?default_template=feed|데모 보러가기}
* @memberof Kakao.Link
*/
export function createDefaultButton(settings) {
if (!settings.objectType || !isOneOf(rules.defaultObjectTypes)(settings.objectType)) {
throw new KakaoError(`objectType should be one of (${rules.defaultObjectTypes.join(', ')})`)
}
const rule = rules[`create${capitalize(settings.objectType)}Button`]
settings = processRules(settings, rule, 'Link.createDefaultButton')
addClickEvent(settings, 'default')
}
/**
* 링크 타입 (Feed, List, Location, Commerce, Text)에 맞는 Object를 구성하여 링크를 쉽게 전송할 수 있습니다.
* @function sendDefault
* @param {DefaultFeedSettings|DefaultListSettings|DefaultLocationSettings|DefaultCommerceSettings|DefaultTextSettings} settings 카카오링크와 관련된 설정을 key/value로 전달합니다.
* @see {@link Kakao.Link.createDefaultButton} 직접 카카오링크 공유 버튼을 제작하여 사용할 필요가 없는 경우 유용합니다.
* @see {@link https://developers.kakao.com/tool/demo/message/kakaolink?method=send&default_template=feed|데모 보러가기}
* @memberof Kakao.Link
*/
export function sendDefault(settings) {
if (!settings.objectType || !isOneOf(rules.defaultObjectTypes)(settings.objectType)) {
throw new KakaoError(`objectType should be one of (${rules.defaultObjectTypes.join(', ')})`)
}
const rule = rules[`send${capitalize(settings.objectType)}`]
settings = processRules(settings, rule, 'Link.sendDefault')
doSend(settings, 'default')
}
/**
* 사이트의 메타 정보를 활용하여 링크를 전송합니다.
* @function createScrapButton
* @param {Object} settings 카카오링크와 관련된 설정을 key/value로 전달합니다.
* @param {String|HTMLElement} settings.container DOM Element 또는 Element의 ID Selector를 넘기면, 해당 Element를 클릭할 때 카카오링크가 전송됩니다.
* @param {String} settings.requestUrl 스크랩 할 사이트 URL, 해당 사이트의 메타 정보를 토대로 링크를 생성
* @param {Number} [settings.templateId] 메시지 아이디, [앱 설정] - [메시지 템플릿 v2] 확인
* @param {Object} [settings.templateArgs] 메시지에 전달할 Argument, ex) {'name':'kakao', 'url':'https://developers.kakao.com'}
* @param {Boolean} [settings.installTalk=false] 카카오톡이 설치되어 있지 않은 경우 마켓의 카카오톡 설치 페이지로 이동합니다.
* @param {Function} [settings.callback] 카카오링크 웹공유에서 공유 버튼 클릭 시 호출되는 콜백 함수 (IE 제외)
* @param {Object|String} [settings.serverCallbackArgs] 카카오링크 공유 시 전송되는 링크 콜백에 포함되는 파라미터. [링크 콜백 가이드로 이동](https://developers.kakao.com/docs/latest/ko/message/js#set-kakaolink-callback)
* @see {@link Kakao.Link.sendScrap} 직접 카카오링크 버튼을 제작하여 사용할 때 이용하세요.
* @see {@link https://developers.kakao.com/tool/demo/message/kakaolink?message_type=scrap|데모 보러가기}
* @memberof Kakao.Link
*/
export function createScrapButton(settings) {
settings = processRules(settings, rules.createScrapButton, 'Link.createScrapButton')
addClickEvent(settings, 'scrap')
}
/**
* 사이트의 메타 정보를 활용하여 링크를 전송합니다.
* @function sendScrap
* @param {Object} settings 카카오링크와 관련된 설정을 key/value로 전달합니다.
* @param {String} settings.requestUrl 스크랩 할 사이트 URL, 해당 사이트의 메타 정보를 토대로 링크를 생성
* @param {Number} [settings.templateId] 메시지 아이디, [앱 설정] - [메시지 템플릿 v2] 확인
* @param {Object} [settings.templateArgs] 메시지에 전달할 Argument, ex) {'name':'kakao', 'url':'https://developers.kakao.com'}
* @param {Boolean} [settings.installTalk=false] 카카오톡이 설치되어 있지 않은 경우 마켓의 카카오톡 설치 페이지로 이동합니다.
* @param {Function} [settings.callback] 카카오링크 웹공유에서 공유 버튼 클릭 시 호출되는 콜백 함수 (IE 제외)
* @param {Object|String} [settings.serverCallbackArgs] 카카오링크 공유 시 전송되는 링크 콜백에 포함되는 파라미터. [링크 콜백 가이드로 이동](https://developers.kakao.com/docs/latest/ko/message/js#set-kakaolink-callback)
* @see {@link Kakao.Link.createScrapButton} 직접 카카오링크 공유 버튼을 제작하여 사용할 필요가 없는 경우 유용합니다.
* @see {@link https://developers.kakao.com/tool/demo/message/kakaolink?method=send&message_type=scrap|데모 보러가기}
* @memberof Kakao.Link
*/
export function sendScrap(settings) {
settings = processRules(settings, rules.sendScrap, 'Link.sendScrap')
doSend(settings, 'scrap')
}
/**
* 원하는 형태의 메시지 템플릿을 만든 후 전송합니다. [메시지 템플릿 가이드로 이동](https://developers.kakao.com/docs/latest/ko/message/message-template)
* @function createCustomButton
* @param {Object} settings 카카오링크와 관련된 설정을 key/value로 전달합니다.
* @param {String|HTMLElement} settings.container DOM Element 또는 Element의 ID Selector를 넘기면, 해당 Element를 클릭할 때 카카오링크가 전송됩니다.
* @param {Number} settings.templateId 메시지 아이디, [앱 설정] - [메시지 템플릿 v2] 확인
* @param {Object} [settings.templateArgs] 메시지에 전달할 Argument, ex) {'name':'kakao', 'url':'https://developers.kakao.com'}
* @param {Boolean} [settings.installTalk=false] 카카오톡이 설치되어 있지 않은 경우 마켓의 카카오톡 설치 페이지로 이동합니다.
* @param {Function} [settings.callback] 카카오링크 웹공유에서 공유 버튼 클릭 시 호출되는 콜백 함수 (IE 제외)
* @param {Object|String} [settings.serverCallbackArgs] 카카오링크 공유 시 전송되는 링크 콜백에 포함되는 파라미터. [링크 콜백 가이드로 이동](https://developers.kakao.com/docs/latest/ko/message/js#set-kakaolink-callback)
* @see {@link Kakao.Link.sendCustom} 직접 카카오링크 버튼을 제작하여 사용할 때 이용하세요.
* @see {@link https://developers.kakao.com/tool/demo/message/kakaolink?message_type=custom|데모 보러가기}
* @memberof Kakao.Link
*/
export function createCustomButton(settings) {
settings = processRules(settings, rules.createCustomButton, 'Link.createCustomButton')
addClickEvent(settings, 'custom')
}
/**
* 원하는 형태의 메시지 템플릿을 만든 후 전송합니다. [메시지 템플릿 가이드로 이동](https://developers.kakao.com/docs/latest/ko/message/message-template)
* @function sendCustom
* @param {Object} settings 카카오링크와 관련된 설정을 key/value로 전달합니다.
* @param {Number} settings.templateId 메시지 아이디, [앱 설정] - [메시지 템플릿 v2] 확인
* @param {Object} [settings.templateArgs] 메시지에 전달할 Argument, ex) {'name':'kakao', 'url':'https://developers.kakao.com'}
* @param {Boolean} [settings.installTalk=false] 카카오톡이 설치되어 있지 않은 경우 마켓의 카카오톡 설치 페이지로 이동합니다.
* @param {Function} [settings.callback] 카카오링크 웹공유에서 공유 버튼 클릭 시 호출되는 콜백 함수 (IE 제외)
* @param {Object|String} [settings.serverCallbackArgs] 카카오링크 공유 시 전송되는 링크 콜백에 포함되는 파라미터. [링크 콜백 가이드로 이동](https://developers.kakao.com/docs/latest/ko/message/js#set-kakaolink-callback)
* @see {@link Kakao.Link.createCustomButton} 직접 카카오링크 공유 버튼을 제작하여 사용할 필요가 없는 경우 유용합니다.
* @see {@link https://developers.kakao.com/tool/demo/message/kakaolink?method=send&message_type=custom|데모 보러가기}
* @memberof Kakao.Link
*/
export function sendCustom(settings) {
settings = processRules(settings, rules.sendCustom, 'Link.sendCustom')
doSend(settings, 'custom')
}
function addClickEvent(settings, linkType) {
const container$ = getElement(settings.container)
if (!container$) {
throw new KakaoError('container is required for KakaoTalk Link: pass in element or id')
}
const clickHandler = e => {
e.preventDefault()
e.stopPropagation()
doSend(settings, linkType)
}
addEvent(container$, 'click', clickHandler)
cleanups.push(() => {
removeEvent(container$, 'click', clickHandler)
})
}
const linkTypeMapper = {
default: {
makeLinkFunc: makeDefaultLink,
requestUrl: '/v2/api/kakaolink/talk/template/default',
},
scrap: {
makeLinkFunc: makeScrapLink,
requestUrl: '/v2/api/kakaolink/talk/template/scrap',
},
custom: {
makeLinkFunc: makeCustomLink,
requestUrl: '/v2/api/kakaolink/talk/template/validate',
},
}
function doSend(settings, linkType) {
const { makeLinkFunc, requestUrl } = linkTypeMapper[linkType]
const linkObj = makeLinkFunc(settings)
const isIpad = (UA.os.ios && UA.platform === 'tablet')
if (!settings.throughTalk || (UA.platform !== 'mobile' && !isIpad)) {
webSender.send(settings, linkType, linkObj)
} else {
talkSender.send(settings, requestUrl, linkObj)
}
}
const cleanups = []
export function cleanup() {
emptyCleanups(cleanups)
}