Example #1
0
def run(content_config, env, variables):
    """
    content_config schema:

    Platform dependent message:
    {
        'text': 'blablabla',
        'choices': [
            {
                'title': 'option 1',
                'payload': '1',
                'acceptable_inputs': ['opt 1']
            },
            ...
        ]
    }
    """
    platform_type = env['platform_type'].value

    m = Message(buttons_text=content_config['text'], variables=variables)

    for i, choice in enumerate(content_config['choices']):
        # Facebook only support 3 buttons
        if i == 3 and platform_type == SupportedPlatform.Facebook:
            break

        b = Message.Button(Message.ButtonType.POSTBACK,
                           choice['title'],
                           payload=TextPayload(choice['payload']),
                           acceptable_inputs=choice['acceptable_inputs'],
                           variables=variables)
        m.add_button(b)

    return [m]
Example #2
0
def run(unused_content_config, env, unused_variables):
    user_input = UserInput()
    msgs = []  # The output messages.

    # output limit and map size
    size = (500, 260)
    if env['platform_type'] == SupportedPlatform.Line:
        max_count = 3
    else:
        max_count = 5

    address = u''  # str. The address user entered.
    filters_str = u''  # str. The filter used this time.

    geocoder = GoogleMapsPlaceAPI(api_key=GOOGLE_STATIC_MAP_API_KEY)

    more_data = user_input.Get('more_data')
    latlng = Memory.Get('latlng', None)  # tuple. User's current location.
    cached_transaction = Memory.Get('cached_transaction', None)
    next_data_index = Memory.Get('next_data_index', max_count)
    if more_data:
        # Yes, user clicks 'more data', dump data from cache.

        if not cached_transaction:
            return [Message(u'請重新輸入地址或條件。')]

        trans = cached_transaction[next_data_index:next_data_index + max_count]
        Memory.Set('next_data_index', next_data_index + max_count)

        if not trans:
            return [Message(u'沒有更多物件了,請重新輸入地址或條件。')]

    else:
        # Nope. User is not entering 'more data'.

        reset = user_input.Get('reset')
        location = user_input.Get('location')

        if reset:
            latlng = Memory.Get('latlng', None)
            rules = None

        # User uploaded current location.
        elif location and 'coordinates' in location:
            latlng = (location['coordinates']['lat'],
                      location['coordinates']['long'])

            rules = Deser(Memory.Get('rules', None))
            if rules:
                rules.AddPureSortingRules(latlng)

        else:  # User entered either an address or criteria; or both.
            query = user_input.Get('query')
            rules = twrealprice_rule.Rules.Create()
            query = rules.ParseQuery(query)

            address = query.strip()
            _LOG.info('User query: address=[%s] filters:[%s]', address,
                      rules.filters)
            if address:
                if latlng:
                    center = {'lat': latlng[0], 'long': latlng[1]}
                else:
                    center = None

                geo_results = geocoder.query_top_n(n=3,
                                                   address=address,
                                                   language='zh_TW',
                                                   region='TW',
                                                   bounds=[[[20.0, 118.0],
                                                            [26.0, 123.0]]],
                                                   center=center)

                if not geo_results:
                    if rules.filters:
                        msgs.append(
                            Message((u'我不認識這個地址:[%s], 但是我認'
                                     u'識條件:[%s]. 請修改一下地址。') %
                                    (address, ' '.join(rules.filters))))
                        address = u''
                    else:
                        return [Message(u'我不認識這個地址:[%s]' % address)]

                if len(geo_results) == 1:
                    latlng = (geo_results[0]['location'][0],
                              geo_results[0]['location'][1])

                if len(geo_results) > 1:
                    m = Message(buttons_text=u'你指的是以下哪一個地址呢?')
                    for r in geo_results:
                        m.add_button(
                            Message.Button(Message.ButtonType.POSTBACK,
                                           r['address'],
                                           payload=LocationPayload(
                                               r['location'], False)))

                    # If user also entered criteria, save it for later query.
                    if rules.filters:
                        Memory.Set('rules', cPickle.dumps(rules))
                        # Postpone the AddPureSortingRules until we get latlng.

                    return [m]

            if not rules.filters:
                # If user didn't enter filter, use the previous one.
                rules = Deser(Memory.Get('rules', None))
                if rules:
                    _LOG.info('User prev rules: %s', rules.filters)
            if rules:
                rules.AddPureSortingRules(latlng)

        next_data_index = max_count

        if not latlng:
            return [Message(u'我還不知道你想查的地方是哪裡。請輸入地址或是送出你的位置。')]

        Memory.Set('rules', cPickle.dumps(rules))
        Memory.Set('latlng', latlng)
        Memory.Set('next_data_index', next_data_index)

        twrealprice = TwRealPrice()
        try:
            trans = twrealprice.nearby_transaction(max_count, latlng, rules)
        except IOError:
            return [Message(u'資料庫找不到,趕快回報給粉絲頁管理員,謝謝。')]

        if rules and rules.filters:
            filters_str = u'篩選條件: 「%s」。' % u'」「'.join(rules.filters)

        if not trans:
            msg = Message(u'對不起,找不到成交行情喔!試試別的地址或條件。')
            msgs.append(msg)
            return msgs

    # Construct main result cards.
    main_map = GoogleStaticMapAPIRequestBuilder(GOOGLE_STATIC_MAP_API_KEY,
                                                size)
    style = MarkerStyle()
    main_map.add_marker(latlng, **style.next())
    for s in trans:
        lat = float(s['latlng'][0])
        lng = float(s['latlng'][1])
        main_map.add_marker((lat, lng), **style.next())

    subtitle = (filters_str + u'搜尋結果僅供參考,詳細完整實價登錄資料,以內政部公佈為準。')

    msg = Message()
    b = Message.Bubble(u'%s附近的成交行情' % address,
                       image_url=main_map.build_url(),
                       subtitle=subtitle)

    msg.add_bubble(b)
    msgs.append(msg)

    # At this point, 'trans' must have data to show.

    i = -1
    for s in trans:
        # In this loop, the strings are concatenated in utf-8 first because the
        # transaction data come with utf-8 encoded.
        try:

            def UnitPrice(s):
                try:
                    return '%.2f萬' % (float(s['單價每平方公尺']) *
                                      twrealprice_rule.M2_PER_PING / 10000)
                except ValueError:
                    return '--.--'

            lines = [
                ' '.join([
                    '%d萬' % (int(s['總價元']) / 10000),
                    '(%s * %.2f坪 + %d萬)' %
                    (UnitPrice(s), float(s['建物移轉總面積平方公尺']) /
                     twrealprice_rule.M2_PER_PING, int(s['車位總價元']) / 10000),
                    '%s(%s)' % (
                        s['建物型態'].split('(')[0],
                        Age(s['建築完成年月']),
                    ),
                ]).decode('utf-8'),
                ' '.join([
                    '%s/共%s' %
                    (s['移轉層次'].replace('層', '樓'), s['總樓層數'].replace('層', '樓')),
                    StreetOnly(s),
                ]).decode('utf-8'),
                ' '.join([
                    RocSlash(s['交易年月日']) + '成交',
                    '%s房%s廳%s衛' %
                    (s['建物現況格局-房'], s['建物現況格局-廳'], s['建物現況格局-衛']),
                    '地坪%.2f' %
                    (float(s['土地移轉總面積平方公尺']) / twrealprice_rule.M2_PER_PING),
                    '車位%.2f坪' %
                    (float(s['車位移轉總面積平方公尺']) / twrealprice_rule.M2_PER_PING),
                    s['車位類別'],
                    s['主要用途'],
                    '備註: ' + s['備註'] if s['備註'] else '',
                ]).decode('utf-8'),
            ]
            if env['platform_type'] == SupportedPlatform.Line:
                title = lines[0]
                subtitle = lines[1] + lines[2]
            else:
                title = lines[0] + lines[1]
                subtitle = lines[2]

            i += 1

            msg = Message()
            msg.add_bubble(
                Message.Bubble((u'%c: ' % (i + ord('A'))) + title,
                               subtitle=subtitle))
            msgs.append(msg)

        except ValueError:
            traceback.print_exc()
            continue

    return msgs
Example #3
0
def run(content_config, unused_env, variables):
    """
    content_config schema:

    Platform dependent message:
    {
        'send_payload_to_current_node': False,
        'api_key': 'google geocoding api key',
        'query_term': 'query term',
        'language': 'zh_TW',
        'region': 'tw',
        'bounds': [
            {'lat': 23.816576, 'long': 119.781068},
            {'lat': 25.314444, 'long': 122.053702}
        ],
        'center': {'lat': 23.816576, 'long': 122.053702}
    }
    """
    query_term = Resolve(content_config['query_term'], variables)

    # Remove stop words
    query_term = re.sub(STOP_WORDS, '', query_term)

    cfg = content_config

    api = GoogleMapsPlaceAPI(content_config['api_key'])

    py_bounds = []
    for b in cfg.get('bounds', []):
        py_bounds.append([(b[0]['lat'], b[0]['long']),
                          (b[1]['lat'], b[1]['long'])])

    results = api.query_top_n(3, query_term, cfg['language'], cfg['region'],
                              py_bounds, cfg.get('center', None))

    in_currrent = content_config['send_payload_to_current_node']

    if not results:
        m = Message(u'對不起,我找不到這個地址, 請重新輸入 >_<')
    elif len(results) == 1:
        m = Message(u'你指的是「%s」嗎?' % results[0]['address'])
        m.add_quick_reply(
            Message.QuickReply(Message.QuickReplyType.TEXT,
                               u'是',
                               payload=LocationPayload(results[0]['location'],
                                                       in_currrent),
                               acceptable_inputs=[u'^對', '(?i)y', '(?i)ok']))
        m.add_quick_reply(
            Message.QuickReply(Message.QuickReplyType.TEXT,
                               u'否',
                               payload=EventPayload('WRONG_ADDRESS', None,
                                                    in_currrent),
                               acceptable_inputs=[u'不', '(?i)n']))
    else:
        m = Message(buttons_text=u'你指的是以下哪一個地址呢?')
        for r in results:
            m.add_button(
                Message.Button(Message.ButtonType.POSTBACK,
                               r['address'],
                               payload=LocationPayload(r['location'],
                                                       in_currrent)))
    return [m]
Example #4
0
def run(content_config, unused_env, variables):
    """
    content_config schema:
    {
        "bot_admins": {
            "platform_user_ident_1": ["bot_id_1", "bot_id_2" ..],
            ...
        }
    }
    """
    user = g.user

    bots = content_config['bot_admins'].get(user.platform_user_ident)
    if not bots:
        return []

    bot = Memory.Get('bot')
    if not bot:
        msgs = [
            Message(u'嗨 {{user.first_name}},你想要操作哪隻機器人呢?', variables=variables)
        ]
        page = 1
        m = Message()
        msgs.append(m)
        bubble = Message.Bubble('第 %d 頁' % page)

        for bot_id in bots:
            bot = Bot.get_by(id=bot_id, single=True)
            if not bot:
                continue

            bubble.add_button(
                Message.Button(Message.ButtonType.POSTBACK,
                               title=bot.name,
                               payload=EventPayload('SELECT_BOT', bot_id)))

            if len(bubble.buttons) == 3:
                m.add_bubble(bubble)
                page += 1
                bubble = Message.Bubble(u'第 %d 頁' % page)

        if len(bubble.buttons):
            m.add_bubble(bubble)

        msgs[-1].add_quick_reply(
            Message.QuickReply(Message.QuickReplyType.TEXT,
                               u'放棄',
                               payload=EventPayload('CONTROL_FLOW', 'reset'),
                               acceptable_inputs=['(?i)giveup', '(?i)reset']))
        return msgs

    operation = Memory.Get('operation')
    if not operation:
        m = Message(buttons_text=u'你想要執行什麼動作呢?')
        m.add_button(
            Message.Button(Message.ButtonType.POSTBACK,
                           title=u'廣播訊息',
                           payload=EventPayload('SELECT_OP', 'broadcast')))
        m.add_button(
            Message.Button(Message.ButtonType.POSTBACK,
                           title=u'放棄',
                           payload=EventPayload('CONTROL_FLOW', 'reset')))
        return [m]

    if operation == 'broadcast':
        broadcast_message = Memory.Get('broadcast_message')
        status = Memory.Get('status')
        if status == 'input_broadcast_message':
            m = Message(u'你可以繼續輸入下一則訊息:')
            m.add_quick_reply(
                Message.QuickReply(
                    Message.QuickReplyType.TEXT,
                    u'完成',
                    payload=EventPayload('MESSAGE_INPUT', 'done'),
                    acceptable_inputs=[u'好了', u'(?i)done', '(?i)y']))
            m.add_quick_reply(
                Message.QuickReply(
                    Message.QuickReplyType.TEXT,
                    u'重來',
                    payload=EventPayload('MESSAGE_INPUT', 'restart'),
                    acceptable_inputs=[u'好了', u'(?i)restart', '(?i)cancel']))
            m.add_quick_reply(
                Message.QuickReply(
                    Message.QuickReplyType.TEXT,
                    u'放棄',
                    payload=EventPayload('CONTROL_FLOW', 'reset'),
                    acceptable_inputs=['(?i)giveup', '(?i)reset']))
            return [m]
        elif not broadcast_message:
            Memory.Set('status', 'input_broadcast_message')
            return [Message(u'請輸入你要廣播的訊息:')]
        elif status == 'preview_message':
            msgs = [Message(u'請確認你要廣播的訊息:')]
            for raw_msg in broadcast_message:
                msgs.append(Message.FromDict(raw_msg))

            m = msgs[-1]
            m.add_quick_reply(
                Message.QuickReply(Message.QuickReplyType.TEXT,
                                   u'確認',
                                   payload=EventPayload(
                                       'CONFIRM_MESSAGE', True),
                                   acceptable_inputs=[u'是', '(?i)y',
                                                      '(?i)ok']))
            m.add_quick_reply(
                Message.QuickReply(
                    Message.QuickReplyType.TEXT,
                    u'取消',
                    payload=EventPayload('CONFIRM_MESSAGE', False),
                    acceptable_inputs=[u'是', '(?i)no', '(?i)cancel']))

            return msgs

    return [Message(u'錯誤的操作')]
Example #5
0
def run_get_content(news_info, variables, limit):
    try:
        event = variables['event']
        content, char_offset, total_length = news_info.get_content(
            event.value['entry_link'], event.value['char_offset'], limit)
        src, alt, pic_index = news_info.get_picture(
            event.value['entry_link'],
            event.value['pic_index'])
    except KeyError:
        return [Message(u'抱歉,有些東西出錯了,請再試一次!')]

    content_ended = char_offset == -1
    picture_ended = pic_index == -1
    all_ended = content_ended and picture_ended

    has_picture = src and alt
    has_content = content != ''

    progress = float(char_offset) / total_length * 100 \
        if char_offset >= 0 else 100.0

    msgs = []
    if has_content and not all_ended:
        m = Message(buttons_text=content)
        m.add_button(Message.Button(
            Message.ButtonType.POSTBACK,
            u'繼續讀 ({:.0f}%)'.format(progress),
            payload=EventPayload('GET_CONTENT', {
                'entry_link': event.value['entry_link'],
                'char_offset': char_offset,
                'pic_index': pic_index,
            }, False)))
        m.add_button(Message.Button(
            Message.ButtonType.WEB_URL, u'去網站讀',
            url=event.value['entry_link']))
        msgs.append(m)
    elif has_content:
        msgs.append(Message(content))

    if has_picture:
        src_msg = Message(image_url=src)
        if alt.strip():
            alt_msg = Message()
            b = Message.Bubble(alt, subtitle=' ')
            # Only append button to the last message, so only append if
            # content is empty
            if not has_content and not all_ended:
                b.add_button(Message.Button(
                    Message.ButtonType.POSTBACK,
                    u'繼續看圖 (文字已結束)',
                    payload=EventPayload('GET_CONTENT', {
                        'entry_link': event.value['entry_link'],
                        'char_offset': char_offset,
                        'pic_index': pic_index,
                    }, False)))
                b.add_button(Message.Button(
                    Message.ButtonType.WEB_URL, u'去網站讀',
                    url=event.value['entry_link']))
            alt_msg.add_bubble(b)
            msgs = [src_msg, alt_msg] + msgs
        else:
            msgs = [src_msg] + msgs

    if all_ended:
        m = Message(u'這則新聞讀完囉!')
        add_quick_reply_keywords(news_info, m, True)

        msgs.append(m)

    return msgs