<commit_before>import logging
import pprint
import random
import re
from functools import wraps

import requests

from .wx import Chats, Group, ResponseError, Robot, User


def dont_raise_response_error(func):
    """
    装饰器：用于避免抛出 ResponseError 错误
    """

    @wraps(func)
    def wrapped(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except ResponseError as e:
            logging.warning('{0.__class__.__name__}: {0}'.format(e))

    return wrapped


def mutual_friends(*args):
    """
    找到多个微信用户的共同好友
    :param args: 每个参数表示一个微信用户，可以是机器人(Robot)，或聊天对象合集(Chats)
    :return: 共同的好友
    """

    class FuzzyUser(User):
        def __init__(self, user):
            super(FuzzyUser, self).__init__(user)

        def __hash__(self):
            return hash((self.nick_name, self.province, self.city, self['AttrStatus']))

    mutual = set()

    for arg in args:
        if isinstance(arg, Robot):
            friends = map(FuzzyUser, arg.friends)
        elif isinstance(arg, Chats):
            friends = map(FuzzyUser, arg)
        else:
            raise TypeError

        if mutual:
            mutual &= set(friends)
        else:
            mutual.update(friends)

    return Chats(mutual)


def ensure_one(found):
    """
    确保列表中仅有一个项，并返回这个项
    :param found: 列表
    :return: 唯一项
    """
    if not isinstance(found, list):
        raise TypeError('expected list, {} found'.format(type(found)))
    elif not found:
        raise ValueError('not found')
    elif len(found) > 1:
        raise ValueError('more than one found')
    else:
        return found[0]


class Tuling(object):
    """
    与 wxpy 深度整合的图灵机器人

    获取 api_key: http://www.tuling123.com/
    API 文档: http://tuling123.com/help/h_cent_webapi.jhtml
    """

    url = 'http://www.tuling123.com/openapi/api'

    def __init__(self, api_key):
        self.session = requests.Session()
        self.api_key = api_key
        self.last_at = dict()

    @property
    def _change_words(self):
        return random.choice((
            '换个话题吧',
            '聊点别的吧',
            '好啦，下一个话题',
            '无言以对呢',
            '这话我接不了…'
        ))

    def do_reply(self, msg, to_member=True):
        """
        回复消息，并返回答复文本
        :param msg: Message 对象
        :param to_member: 若消息来自群聊，回复 @发消息的群成员
        :return: 答复文本
        """
        ret = self.reply_text(msg, to_member)
        msg.reply(ret)
        return ret

    def reply_text(self, msg, to_member=True):
        """
        返回消息的答复文本
        :param msg: 消息 (wxpy.Message)
        :param to_member: 若消息来自群聊，回复 @发消息的群成员
        :return: 答复文本
        """

        def process_answer():<commit_msg>update Tuling<commit_after>import logging
import pprint
import random
import re
from functools import wraps

import requests

from .wx import Chats, Group, ResponseError, Robot, User


def dont_raise_response_error(func):
    """
    装饰器：用于避免抛出 ResponseError 错误
    """

    @wraps(func)
    def wrapped(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except ResponseError as e:
            logging.warning('{0.__class__.__name__}: {0}'.format(e))

    return wrapped


def mutual_friends(*args):
    """
    找到多个微信用户的共同好友
    :param args: 每个参数表示一个微信用户，可以是机器人(Robot)，或聊天对象合集(Chats)
    :return: 共同的好友
    """

    class FuzzyUser(User):
        def __init__(self, user):
            super(FuzzyUser, self).__init__(user)

        def __hash__(self):
            return hash((self.nick_name, self.province, self.city, self['AttrStatus']))

    mutual = set()

    for arg in args:
        if isinstance(arg, Robot):
            friends = map(FuzzyUser, arg.friends)
        elif isinstance(arg, Chats):
            friends = map(FuzzyUser, arg)
        else:
            raise TypeError

        if mutual:
            mutual &= set(friends)
        else:
            mutual.update(friends)

    return Chats(mutual)


def ensure_one(found):
    """
    确保列表中仅有一个项，并返回这个项
    :param found: 列表
    :return: 唯一项
    """
    if not isinstance(found, list):
        raise TypeError('expected list, {} found'.format(type(found)))
    elif not found:
        raise ValueError('not found')
    elif len(found) > 1:
        raise ValueError('more than one found')
    else:
        return found[0]


class Tuling(object):
    """
    与 wxpy 深度整合的图灵机器人

    获取 api_key: http://www.tuling123.com/
    API 文档: http://tuling123.com/help/h_cent_webapi.jhtml
    """

    url = 'http://www.tuling123.com/openapi/api'

    def __init__(self, api_key):
        self.session = requests.Session()
        self.api_key = api_key
        self.last_at = dict()

    @property
    def _change_words(self):
        return random.choice((
            '换个话题吧',
            '聊点别的吧',
            '下一个话题',
            '无言以对呢',
            '这话我接不了'
        ))

    def do_reply(self, msg, to_member=True):
        """
        回复消息，并返回答复文本
        :param msg: Message 对象
        :param to_member: 若消息来自群聊，回复 @发消息的群成员
        :return: 答复文本
        """
        ret = self.reply_text(msg, to_member)
        msg.reply(ret)
        return ret

    def reply_text(self, msg, to_member=True):
        """
        返回消息的答复文本
        :param msg: 消息 (wxpy.Message)
        :param to_member: 若消息来自群聊，回复 @发消息的群成员
        :return: 答复文本
        """

        def process_answer():
{'fraction_non_alphanumeric': 0.11544227886056972, 'fraction_numerical': 0.004872563718140929, 'mean_word_length': 2.0921205098493627, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7169150', 'n_tokens_mistral': 1962, 'n_tokens_neox': 2033, 'n_words': 394}