콘텐츠로 이동

텍스트 어뷰징 탐지

텍스트 어뷰징 탐지 API는 텍스트에서 어뷰징(금칙어, 스팸 광고)을 탐지하고 확인하는 API입니다.

사전 준비

Hive 콘솔 > AI 서비스 > 어뷰징 탐지 > 텍스트 어뷰징 탐지 메뉴에 접근할 수 있는지 확인하고, 접근이 안 되면 Hive 콘솔 권한 관리 가이드를 참고해 메뉴 접근 권한을 얻습니다. 텍스트 어뷰징 탐지에서 새 프로젝트를 등록합니다.

텍스트 어뷰징 여부 판단

텍스트를 전송한 후 이 텍스트가 스팸성 광고인지 텍스트에 금칙어가 포함되었는지 등을 판단해 결과를 반환합니다.

Request URL

LIVE URL https://tads.withhive.com/cads2/send-text-data
Sandbox URL https://sandbox-tads.withhive.com/cads2/send-text-data
HTTP Method POST
Content-Type application/json

Request body

필드명 설명 타입 필수
project_key 프로젝트 키 String Y
text_log 텍스트 정보 Object Y

text_log

필드명 설명 타입 필수
text_array 텍스트와 텍스트 전송 시간이 들어있는 객체들의 배열 Array(Object) Y
text_count text_array에 있는 객체 개수 Integer Y

text_array에 있는 객체

필드명 설명 타입 필수
time_stamp 텍스트 전송 시간(UTC 기준 ISO 형식 시간 문자열, 예시: 2024-01-30T10:35:49.95457+09:00) String Y
text_info JSON 객체Hive 콘솔에서 얻은 암호키를 사용해 AES256 방식으로 암호화한 문자열입니다. 최대 크기는 5KB입니다. 암호화 방법에 대한 자세한 내용은 예제 코드를 참고하세요. String Y

text\_info JSON 객체

아래 양식을 따라 JSON 객체를 생성 후, 이를 AES256 방식으로 암호화하여 text_info 문자열을 만듭니다.

필드명 설명 타입 필수
user_id 사용자 고유 ID 번호 String Y
lang_code 언어 코드(ISO 639-1 기반)
  • 한국어: ko
  • 영어: en
  • 일본어: ja
  • 중문 간체: zh-hans
  • 중문 번체: zh-hant
  • 에스파냐: es
  • 러시아: ru
  • 독일어: de
  • 프랑스어: fr
  • 포르투갈어: pt
  • 이태리어: it
  • 태국어: th
  • 인도네시아어: id
  • 터키어: tr
  • 말레이시아어: ms
  • 베트남어: vi
String Y
text 어뷰징 여부를 체크할 텍스트 String Y
text_type 텍스트가 채팅 텍스트인 경우, 3가지 채팅 형태중 하나입니다.
  • "chat_party": 파티 채팅
  • "chat_guild": 길드 채팅
  • "chat_whisper": 귓속말
String N
room_num 텍스트가 채팅 텍스트인 경우, 채팅방 번호입니다. String N
channel_info 텍스트가 채팅 텍스트인 경우, 채팅 채널 정보입니다. String N

Response

필드명 설명 타입
result_code 응답 코드 String
result_text 응답 코드 설명 String
result_array 탐지 결과를 담은 배열 Array(Object)

result_array

필드명 설명 타입
tads_result 탐지 결과 Object
text_result 원문 텍스트와 탐지 결과를 토대로 원문 텍스트에 마스킹을 적용한 결과 Object

tads_result

필드명 설명 타입
forbidden_yn 금칙어 탐지 여부(0: 텍스트에서 금칙어 미발견, 1: 텍스트에서 금칙어 발견) String
spam_yn 광고 탐지 여부(0: 텍스트가 스팸성 광고가 아님, 1: 텍스트가 스팸성 광고임) String
aug_yn 묶음 처리 여부(0: 묶음 처리되지 않음, 1: 묶음 처리됨) String
long_yn 긴 문자열 여부로 5,000자 이상이면 어뷰징 여부를 탐지할 수 없음 (0: 5,000자 이하, 1: 5,000자 초과) String

text_result

필드명 설명 타입
text 어뷰징 여부를 체크하려는 텍스트 String
masking_text text에 마스킹을 적용한 텍스트(Hive 콘솔에서 마스킹 설정을 하지 않았거나 tads_result.forbidden_yn값이 0이면 text와 동일) String

Response code

코드 텍스트 비고
200 "success" 성공
500 "Incorrect request" 요청에 오류가 있습니다. Request URL과 Reqest Body가 정확한지 확인하세요.
501 "Incorrect Data Count" 전달된 텍스트의 카운트가 일치하지 않습니다. text_count 값과 text_array의 길이가 일치해야 합니다.
502 "Incorrect Secret Key" 올바르지 않은 암호키 값입니다. 프로젝트 관리에서 해당 프로젝트 암호키를 확인하세요.
503 "Unregistered ProjectKey" 올바르지 않은 프로젝트 키 값입니다. 프로젝트 관리에서 해당 프로젝트의 프로젝트 키를 확인하세요.
506 "System Error" 네트워크 오류 등 내부 오류입니다. 일정 시간 후 API를 다시 호출하세요.
507 "The size of message is too large" 텍스트 크기가 너무 큽니다. text_array 최대 크기는 5KB입니다. 메세지 크기를 줄여주세요.

Request example

import json
import base64
import requests
from datetime import datetime
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad

def encrypt(text, user_id, lang_code, secret_key, channel_info=None, room_num=None, text_type=None) -> str: ## 암호화 코드
        aes = AES.new(secret_key, AES.MODE_ECB)
        jsonData =  {"text_type": text_type, ## 필요 없을 경우 제외
                                "room_num" : room_num, ## 필요 없을 경우 제외
                                "user_id": user_id,
                                "channel_info" : channel_info, ## 필요 없을 경우 제외
                                "lang_code": lang_code,
                                "text": text}
        rawJsonStr = json.dumps(jsonData)
        paddedStr = pad(rawJsonStr.encode("utf-8"),AES.block_size)
        encrypted_data = aes.encrypt(paddedStr)
        encrypted_data_b64 = base64.b64encode(encrypted_data).decode("utf-8")
        return encrypted_data_b64

project_key = <PROJECT_KEY>
secret_key = <SECRET_KEY>
now = datetime.now().astimezone().isoformat()
lang_code = "ko"
user_id = "432414"
channel_info = "4342314" ## 필요 없을 경우 제외
room_num = "12312" ## 필요 없을 경우 제외
text_type = "chat_whisper" ## 필요 없을 경우 제외
url = "https://tads.withhive.com/cads2/send-text-data"

payload =  {"project_key": project_key,
                                            "text_log": {
                                                            "text_count": 2, ## text_array의 개수에 맞춰서 설정
                                                            "text_array": [
                                                                                        {"time_stamp": now,
                                                                                        "text_info": encrypt(text=str("테스트1"), 
                                                                                                                        user_id=user_id,
                                                                                                                        channel_info=channel_info, ## 필요 없을 경우 제외
                                                                                                                        room_num=room_num, ## 필요 없을 경우 제외
                                                                                                                        text_type=text_type, ## 필요 없을 경우 제외
                                                                                                                        lang_code=lang_code,
                                                                                                                        secret_key=secret_key)},
                                                                                        {"time_stamp": now,
                                                                                        "text_info": encrypt(text=str("테스트2"), 
                                                                                                                        user_id=user_id,
                                                                                                                        channel_info=channel_info, ## 필요 없을 경우 제외
                                                                                                                        room_num=room_num, ## 필요 없을 경우 제외
                                                                                                                        text_type=text_type, ## 필요 없을 경우 제외
                                                                                                                        lang_code=lang_code,
                                                                                                                        secret_key=secret_key)}]},}

res = requests.post(url, data=json.dumps(payload), headers={"Content-Type": "application/json"})
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

import java.util.Base64;
import org.jooq.tools.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import lombok.extern.slf4j.Slf4j;

import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

@Slf4j
public class TadsComponent {

        @Autowired
        RestTemplate restTemplate;

        @Autowired
        ObjectMapper objectMapper;


public void sendHttp() throws Exception{
        String projectKey =  <PROJECT_KEY>; // 프로젝트키 입력
        String secretKey =  <SECRET_KEY>;  // 암호키 입력

        String url = "https://tads.withhive.com/cads2/send-text-data";
        String user_id = "432414";
        String channel_info = "4342314"; // 필요 없을 경우 제외
        String room_num = "12312"; // 필요 없을 경우 제외
        String text_type = "chat_whisper"; // 필요 없을 경우 제외
        String lang_code = "ko";
        String text_1 = "테스트1";
        String text_2 = "테스트2";

        DateTimeFormatter formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
        ZonedDateTime now = ZonedDateTime.now();

        Map<String, Object> payload = new HashMap<>();
        payload.put("project_key", projectKey);

        Map<String, Object> textLog = new HashMap<>();
        textLog.put("text_count", 2); // text_array의 개수에 맞춰서 설정

        Map<String, Object> textArray1 = new HashMap<>();
        textArray1.put("time_stamp", now.format(formatter));
        textArray1.put("text_info", encrypt(text_1, user_id, channel_info, room_num, text_type, lang_code, secretKey));


        Map<String, Object> textArray2 = new HashMap<>();
        textArray2.put("time_stamp", now.format(formatter));
        textArray2.put("text_info", encrypt(text_2, user_id, channel_info, room_num, text_type, lang_code, secretKey));

        Object[] textArrayObj = {textArray1, textArray2};
        textLog.put("text_array", textArrayObj);
        payload.put("text_log", textLog);
        JsonNode callBodyNode = objectMapper.valueToTree(payload);
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/json");
        HttpEntity<String> entity = new HttpEntity<>(callBodyNode.toString(), headers);
        ResponseEntity<String> responseEntity =  restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
        int responseStatusCode =  responseEntity.getStatusCodeValue();
        String responseBodyString = responseEntity.getBody();
        JsonNode responseBodyNode = objectMapper.readTree(responseBodyString);
        return;
}

public static String encrypt(String text, String UserId, String channelInfo, String roomNum, String textType, String langCode, String secretKey) {
        try {
                Cipher aes = Cipher.getInstance("AES/ECB/PKCS5Padding");
                SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(), "AES");
                aes.init(Cipher.ENCRYPT_MODE, secretKeySpec);
                Map<String,Object> map = new HashMap<String,Object>();
                map.put("room_num", roomNum); // 필요 없을 경우 제외
                map.put("channel_info", channelInfo); // 필요 없을 경우 제외
                map.put("lang_code", langCode);
                map.put("text", text);
                map.put("text_type", textType); // 필요 없을 경우 제외
                map.put("user_id", UserId);
                String encrypt_str = JSONObject.toJSONString(map);
                byte[] paddedData = padString(encrypt_str).getBytes();
                byte[] encryptedData = aes.doFinal(paddedData);
                return Base64.getEncoder().encodeToString(encryptedData);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
                e.printStackTrace();
                return null;
        }
}
private static String padString(String source) {
        char paddingChar = ' ';
        int size = 16;
        int x = source.length() % size;
        int padLength = size - x;
        StringBuilder paddedString = new StringBuilder(source);
        for (int i = 0; i < padLength; i++) {
                paddedString.append(paddingChar);
        }
        return paddedString.toString();
}} // 암호화 코드

Response example

{
    "result": {
        "result_array": '[
                        {"tads_result":{
                            "forbidden_yn":"0",
                            "spam_yn":"0",
                            "aug_yn":"0",
                            "long_yn":"0"},
                        "text_result":{
                            "text":"테스트1",
                            "masking_text":"테스트1"
                        }},
                        {"tads_result":{
                            "forbidden_yn":"0",
                            "spam_yn":"0",
                            "aug_yn":"0",
                            "long_yn":"0"},
                        "text_result":{
                            "text":"테스트2",
                            "masking_text":"테스트2"
                        }}
                            ]',
        "result_code": "200",
        "result_text": "success"
    }
}