Exemplo n.º 1
0
def run(content_config, env, variables):
    """
    content_config schema:

    Platform independent message:
    {
        'text': 'text to send'
    }

    Platform dependent message:
    {
        'text': {
            'Facebook': 'text to send',
            'Line': 'text to send',
            ...
        }
    }
    """
    text = content_config['text']

    if not isinstance(text, list):
        text = [text]

    # Platform independent message
    if not isinstance(text[0], dict):
        msgs = [Message(t, variables=variables) for t in text]
    else:
        platform_type = env['platform_type'].value
        msgs = [Message(t[platform_type], variables=variables) for t in text]

    for qr in content_config.get('quick_replies', []):
        msgs[-1].add_quick_reply(
            Message.QuickReply.FromDict(qr, variables=variables))

    return msgs
Exemplo n.º 2
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]
Exemplo n.º 3
0
def render_cards(news_info, news):
    """Render cards given a list of new entries."""
    if not len(news):
        return [Message(u'找不到你要的新聞喔!')]

    m = Message()
    for n in news:
        image_url = (n.image_url if n.image_url != '' else
                     get_default_image(n.source))
        b = Message.Bubble(n.title,
                           image_url=image_url,
                           subtitle=n.description)
        b.add_button(Message.Button(
            Message.ButtonType.POSTBACK,
            u'在這讀', payload=EventPayload('GET_CONTENT', {
                'entry_link': n.link,
                'char_offset': 0,
                'pic_index': 1,
            }, False)))
        b.add_button(Message.Button(
            Message.ButtonType.WEB_URL, u'去網站讀',
            url=n.link))
        b.add_button(Message.Button(Message.ButtonType.ELEMENT_SHARE))
        m.add_bubble(b)

    add_quick_reply_keywords(news_info, m, True)
    return [m]
Exemplo n.º 4
0
def run(content_config, env, variables):
    news_info = NewsInfo()
    n_items = content_config.get('n_items', DEFAULT_N_ITEMS)
    user_id = GetUserId()

    limit = 200
    if env['platform_type'] == SupportedPlatform.Line:
        limit = 160

    if content_config['mode'] == 'get_content':
        return run_get_content(news_info, variables, limit)

    if content_config['mode'] == 'list_by_source':
        source_name = Resolve(content_config['query_term'], variables)
        return render_cards(
            news_info,
            news_info.trending(user_id, source_name, n_items))

    elif content_config['mode'] == 'prompt':
        m = Message(u'想要知道什麼呢?今天這些字最夯!')
        add_quick_reply_keywords(news_info, m)
        return [m]

    elif content_config['mode'] == 'search':
        query_term = Resolve(content_config['query_term'], variables)
        return render_cards(
            news_info,
            (news_info.search(query_term, n_items)
             if query_term else news_info.trending(user_id)))

    return render_cards(news_info, news_info.trending(user_id))
Exemplo n.º 5
0
def run(content_config, env, variables):
    """
    content_config schema:

    Platform independent message:
    {
        'messages': [Message, ...]
    }

    Platform dependent message:
    {
        'message': {
            'Facebook': [Message,  ... ]
            'Line': [Message, ... ]
            ...
        }
    }
    """
    messages = content_config.get('messages')
    msgs = []

    if not isinstance(messages, list):
        platform_type = env['platform_type'].value
        messages = messages[platform_type]

    for message in messages:
        msgs.append(Message.FromDict(message, variables))

    for quick_reply in content_config.get('quick_replies', []):
        msgs[-1].add_quick_reply(Message.QuickReply.FromDict(quick_reply))

    return msgs
Exemplo n.º 6
0
def run(content_config, unused_env, variables):
    """
    content_config schema:
    {
       "response": "{{variable}",
    }
    """
    m = Message(Resolve(content_config['response'], variables))
    return [m]
Exemplo n.º 7
0
def run(content_config, unused_env, variables):
    msgs = []  # The output messages.

    url = Render(content_config['url'], variables)
    method = content_config.get('method', 'post')
    params = content_config.get('params', [])
    params = [
        (Render(x[0], variables), Render(x[1], variables))
        for x in params]

    try:
        js = FetchData(url=url, params=params, method=method)

        for m in js:
            msg = Message.FromDict(m)
            msgs.append(msg)

    except Exception as e:
        _LOG.exception(e)
        msgs.append(Message(u'我好像壞掉了,快通知管理員。'))

    return msgs
Exemplo n.º 8
0
def schema():
    return {
        'type': 'object',
        'required': ['messages'],
        'additionalProperties': False,
        'properties': {
            'messages': {
                'oneOf': [{
                    'type': 'array',
                    'items': Message.schema()
                }, {
                    'type': 'object',
                    'required': ['Facebook', 'Line'],
                    'additionalProperties': False,
                    'properties': {
                        'Facebook': {
                            'type': 'array',
                            'items': Message.schema()
                        },
                        'Line': {
                            'type': 'array',
                            'items': Message.schema()
                        }
                    }
                }]
            },
            'quick_replies': {
                'type': 'array',
                'items': {'$ref': '#/definitions/quick_reply'}
            }
        },
        'definitions': {
            'button': Message.Button.schema(),
            'bubble': Message.Bubble.schema(),
            'list_item': Message.ListItem.schema(),
            'quick_reply': Message.QuickReply.schema()
        }
    }
Exemplo n.º 9
0
def add_quick_reply_keywords(news_info, message, show_related=False):
    """Install QuickReply keywords into message."""
    keywords = news_info.get_keywords(MAX_KEYWORDS)
    reply_kws = []
    if show_related:
        query_term = CollectedData.GetLast('query_term', '')
        related_kws = news_info.get_related_keywords(query_term, 3)

        reply_kws = [kw.name for kw in related_kws]
        for kw in keywords:
            if len(reply_kws) < MAX_KEYWORDS and kw.name not in reply_kws:
                reply_kws.append(kw.name)
    else:
        reply_kws += [kw.name for kw in keywords]

    for kw in reply_kws:
        message.add_quick_reply(Message.QuickReply(
            Message.QuickReplyType.TEXT, kw))

    message.add_quick_reply(Message.QuickReply(
        Message.QuickReplyType.TEXT, u'熱門新聞'))
    message.add_quick_reply(Message.QuickReply(
        Message.QuickReplyType.TEXT, u'搜尋'))
Exemplo n.º 10
0
def run(content_config, unused_env, unused_variables):
    if content_config['target'] == 'memory':
        target = Memory
    else:
        target = Settings

    if content_config['mode'] == 'set':
        target.Set('data', content_config['data'])
    elif content_config['mode'] == 'get':
        return [Message(target.Get('data'))]
    elif content_config['mode'] == 'clear':
        target.Clear()

    return []
Exemplo n.º 11
0
def render_dramas(dramas):
    """Render cards given a list of dramas"""
    if not len(dramas):
        return Message(u'找不到你要的劇喔!')

    m = Message()
    for d in dramas:
        b = Message.Bubble(d.name,
                           image_url=CacheImage(d.image_url),
                           subtitle=d.description)
        if d.subscribed:
            b.add_button(
                Message.Button(Message.ButtonType.POSTBACK,
                               u'取消追蹤',
                               payload=EventPayload('UNSUBSCRIBE', {
                                   'drama_id': d.id,
                               }, False)))
        else:
            b.add_button(
                Message.Button(Message.ButtonType.POSTBACK,
                               u'追蹤我',
                               payload=EventPayload('SUBSCRIBE', {
                                   'drama_id': d.id,
                               }, False)))

        b.add_button(
            Message.Button(Message.ButtonType.POSTBACK,
                           u'我想看前幾集',
                           payload=EventPayload(
                               'GET_HISTORY', {
                                   'drama_id': d.id,
                                   'from_episode': 0,
                                   'backward': True,
                               })))
        b.add_button(Message.Button(Message.ButtonType.ELEMENT_SHARE))
        m.add_bubble(b)
    return m
Exemplo n.º 12
0
def run(unused_content_config, unused_env, unused_variables):
    m = Message()
    b = Message.Bubble('Tap postback')
    b.add_button(
        Message.Button(Message.ButtonType.POSTBACK,
                       'Postback',
                       payload=TextPayload('PAYLOAD_TEXT')))
    m.add_bubble(b)
    return [m]
Exemplo n.º 13
0
def run(content_config, unused_env, variables):
    """
    content_config schema:
    {
       "type": "random or query",
       "term": "query term if type is query",
       "max_count": 5, // max number of images to return
       "auth": {
           "client_id": "imgur client_id",
           "client_secret": "imgur client_secret"
       }
    }
    """
    client = imgurpython.ImgurClient(content_config['auth']['client_id'],
                                     content_config['auth']['client_secret'])

    if content_config['type'] == 'random':
        images = [
            x for x in client.gallery_random() if isinstance(x, GalleryImage)
        ]
    else:
        term = Resolve(content_config['term'], variables)
        images = [
            x for x in client.gallery_search(term)
            if isinstance(x, GalleryImage)
        ]

    images = random.sample(images, int(content_config['max_count']))

    m = Message()
    for i in images:
        c = Message.Bubble(i.title, i.link[:-4], i.link, i.description)
        c.add_button(
            Message.Button(Message.ButtonType.WEB_URL,
                           'Source',
                           url=i.link[:-4]))
        c.add_button(
            Message.Button(Message.ButtonType.POSTBACK,
                           'Like',
                           payload=TextPayload('like %s' % i.link)))
        m.add_bubble(c)

    return [Message('Here are the images you requested'), m]
Exemplo n.º 14
0
 def append_categories_to_quick_reply(m):
     m.add_quick_reply(
         Message.QuickReply(Message.QuickReplyType.TEXT, u'荼蘼'))
     m.add_quick_reply(
         Message.QuickReply(Message.QuickReplyType.TEXT, u'The K2 第十集'))
     m.add_quick_reply(
         Message.QuickReply(Message.QuickReplyType.TEXT, u'熱門韓劇'))
     m.add_quick_reply(
         Message.QuickReply(Message.QuickReplyType.TEXT, u'熱門日劇'))
     m.add_quick_reply(
         Message.QuickReply(Message.QuickReplyType.TEXT, u'熱門台劇'))
     m.add_quick_reply(
         Message.QuickReply(Message.QuickReplyType.TEXT, u'熱門陸劇'))
     m.add_quick_reply(
         Message.QuickReply(Message.QuickReplyType.TEXT, u'通知設定'))
     return [m]
Exemplo n.º 15
0
def run(content_config, unused_env, variables):
    """
    content_config schema:
    {
        "settings": {
            "key1": "value1",
            "key2": "value2",
        },
        "message": "message"
    }
    """

    for key, value in content_config['settings'].iteritems():
        if isinstance(value, str):
            value = Render(value, variables)
        Settings.Set(key, value)

    return [Message(content_config['message'], variables=variables)]
Exemplo n.º 16
0
def run(content_config, unused_env, variables):
    """
    content_config schema:
    {
        "query_url": "http://ecshweb.pchome.com.tw/search/v3.3/all/results?"
                     "q=%s&page=1&sort=rnk/dc",
        "term": "{{matches#1}}",
        "max_count": 7,
        "list": "prods",
        "attributes": {
              "title": "${{price}}: {{name}}",
              "image": "http://a.ecimg.tw/{{picB}}",
              "item_url": "http://24h.pchome.com.tw/{{Id}}",
              "subtitle": "{{describe}}",
              "buttons": [
                  {
                      "type": "web_url",
                      "title": "商品頁面",
                      "url": "http://24h.pchome.com.tw/{{Id}}"
                  }
              ]
          }
    }
    """
    url = content_config['query_url']
    timeout = content_config.get('timeout_secs', DEFAULT_TIMEOUT_SECS)

    if 'term' in content_config:
        term = Resolve(content_config['term'], variables)
        url = url % urllib.quote(term.encode('utf-8'))

    try:
        content = json.loads(urllib2.urlopen(url, timeout=timeout).read())
    except Exception:
        return []

    max_count = content_config['max_count']
    attributes = content_config['attributes']
    elements = content.get(content_config['list'], [])

    if len(elements) > max_count:
        elements = elements[:max_count]

    m = Message()
    for element in elements:
        var = dict(variables, **element)
        bub = Message.Bubble(title=attributes['title'],
                             item_url=attributes.get('item_url', None),
                             image_url=attributes['image'],
                             subtitle=attributes.get('subtitle', None),
                             variables=var)

        for b in attributes.get('buttons', []):
            payload = b.get('payload', None)
            bub.add_button(
                Message.Button(
                    b_type=Message.ButtonType(b['type']),
                    title=b['title'],
                    url=b.get('url', None),
                    payload=TextPayload(payload) if payload else None,
                    variables=var))

        m.add_bubble(bub)

    return [m]
Exemplo n.º 17
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
Exemplo n.º 18
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]
Exemplo n.º 19
0
def run(parser_config, user_input, unused_as_root):
    """
    {
      "links": [
        {
          "action_ident": "continue",
          "end_node_id": null,
          "ack_message": ""
        },
        {
          "action_ident": "done",
          "end_node_id": "[[root]]",
          "ack_message": ""
        }
      ]
    }
    """
    if user_input.text:
        if u'重設' in user_input.text or 'reset' in user_input.text.lower():
            Memory.Clear()
            return ParseResult(ack_message=u'讓我們重新開始吧!')

    if user_input.event:
        event = user_input.event
        if event.key == 'CONTROL_FLOW':
            if event.value == 'reset':
                Memory.Clear()
                return ParseResult(parser_config['done'], ack_message=u'放棄操作')
        elif event.key == 'SELECT_BOT':
            Memory.Set('bot', event.value)
        elif event.key == 'SELECT_OP':
            Memory.Set('operation', event.value)
        elif event.key == 'MESSAGE_INPUT':
            if event.value == 'done':
                Memory.Set('status', 'preview_message')
            elif event.value == 'restart':
                Memory.Set('broadcast_message', None)
                Memory.Set('status', None)
        elif event.key == 'CONFIRM_MESSAGE':
            if event.value:
                bot = Bot.get_by(id=Memory.Get('bot'), single=True)
                if not bot:
                    return ParseResult(ack_message=u'發生錯誤,找不到對應的' u'機器人')
                msgs = [
                    Message.FromDict(raw_msg)
                    for raw_msg in Memory.Get('broadcast_message')
                ]
                BroadcastMessage(bot, msgs)
                Memory.Clear()
                return ParseResult(parser_config['done'],
                                   ack_message=u'您的訊息已送出!')
            else:
                Memory.Set('broadcast_message', None)

    status = Memory.Get('status')
    if status == 'input_broadcast_message':
        broadcast_message = Memory.Get('broadcast_message') or []
        broadcast_message.append(user_input.raw_message)
        Memory.Set('broadcast_message', broadcast_message)

    return ParseResult(skip_content_module=False)
Exemplo n.º 20
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'錯誤的操作')]
Exemplo n.º 21
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
Exemplo n.º 22
0
def run(content_config, unused_env, variables):
    """
    content_config schema:
    {
       "api_key": "api_key",
       "send_payload_to_current_node": true,
       "location": "location variables",
       "max_count": 3
       "distance_threshold": 0.050,
       "display_weather": true
    }
    """

    location = Resolve(content_config['location'], variables)
    if 'coordinates' not in location:
        return [Message('不正確的輸入,請重新輸入')]

    c = (location['coordinates']['lat'], location['coordinates']['long'])
    youbike = YoubikeInfo()

    k = content_config.get('max_count', 5)
    size = (500, 260)

    stations = youbike.find_knn(k, c, content_config['distance_threshold'])
    if not stations:
        return [Message('對不起,這裡附近沒有 Ubike 站喔!')]

    m = GoogleStaticMapAPIRequestBuilder(content_config['api_key'], size)
    m.add_marker(c, 'purple')
    for s in stations:
        m.add_marker((float(s['lat']), float(s['lng'])))

    msgs = []

    # Construct main result cards.
    msg = Message()
    b = Message.Bubble(u'附近的 Ubike 站點',
                       image_url=m.build_url(),
                       subtitle=u'以下是最近的 %d 個站點' % k)

    best = stations[0]
    for s in stations:
        if s['sbi'] > 0:
            best = s
            break

    best_gps_coord = (float(best['lat']), float(best['lng']))
    b.add_button(Message.Button(Message.ButtonType.WEB_URL, u'帶我去',
                                url=m.build_navigation_url(best_gps_coord)))

    to_current = content_config['send_payload_to_current_node']
    b.add_button(Message.Button(Message.ButtonType.POSTBACK, u'再次查詢',
                                payload=LocationPayload(c, to_current)))
    msg.add_bubble(b)

    for s in stations:
        m.clear_markers()
        m.add_marker(c, 'purple')

        gps_coord = (float(s['lat']), float(s['lng']))
        m.add_marker(gps_coord, color='red')

        sbi, bemp = int(s['sbi']), int(s['bemp'])
        subtitle = u'剩餘數量: %d\n空位數量: %d\n' % (sbi, bemp)

        if sbi < 5:
            subtitle += (u'預計進車時間: %d 分鐘\n' %
                         youbike.average_waiting_time(
                             str(s['sno']), youbike.Direction.In))
        if bemp < 5:
            subtitle += (u'預計出位時間:%d 分鐘\n' %
                         youbike.average_waiting_time(
                             str(s['sno']), youbike.Direction.Out))

        b = Message.Bubble(s['ar'], image_url=m.build_url(), subtitle=subtitle)
        b.add_button(Message.Button(Message.ButtonType.WEB_URL,
                                    u'地圖導航',
                                    url=m.build_navigation_url(gps_coord)))
        msg.add_bubble(b)

    msgs.append(msg)

    if content_config['display_weather'] and 'weather' in best:
        # See http://openweathermap.org/weather-conditions
        # for weather codes.
        weather = best['weather']
        code = best['weather']['weather_code']
        temp = weather['temp']
        time = GetUserTime()

        if code / 100 == 3 or code in [500, 501, 520]:
            msgs.append(Message(u'提醒你,現在外面天雨路滑,騎車小心!'
                                u'記得帶傘或穿件雨衣唷'))
        elif (code / 100 == 2 or
              code in [502, 503, 504, 511, 521, 522, 531, 901, 902]):
            msgs.append(Message(u'現在外面大雨滂沱,不如叫個 Uber 吧!'))
        elif temp >= 30 and time.hour >= 10 and time.hour <= 16:
            msgs.append(Message(u'提醒你,現在外面天氣炎熱 (攝氏 %.1f 度) ,'
                                u'記得做好防曬唷' % temp))
    return msgs
Exemplo n.º 23
0
def run(content_config, unused_env, variables):
    drama_info = DramaInfo()
    n_items = content_config.get('n_items', DEFAULT_N_ITEMS)
    user_id = GetUserId()

    def append_categories_to_quick_reply(m):
        m.add_quick_reply(
            Message.QuickReply(Message.QuickReplyType.TEXT, u'荼蘼'))
        m.add_quick_reply(
            Message.QuickReply(Message.QuickReplyType.TEXT, u'The K2 第十集'))
        m.add_quick_reply(
            Message.QuickReply(Message.QuickReplyType.TEXT, u'熱門韓劇'))
        m.add_quick_reply(
            Message.QuickReply(Message.QuickReplyType.TEXT, u'熱門日劇'))
        m.add_quick_reply(
            Message.QuickReply(Message.QuickReplyType.TEXT, u'熱門台劇'))
        m.add_quick_reply(
            Message.QuickReply(Message.QuickReplyType.TEXT, u'熱門陸劇'))
        m.add_quick_reply(
            Message.QuickReply(Message.QuickReplyType.TEXT, u'通知設定'))
        return [m]

    if content_config['mode'] == 'subscribe':
        event = variables['event']
        drama_id = event.value['drama_id']
        Memory.Set('last_query_drama_id', drama_id)
        drama_info.subscribe(user_id, drama_id)

        episodes = drama_info.get_history(drama_id=drama_id,
                                          from_episode=0,
                                          backward=True)
        return ([
            Message(u'謝謝您的追蹤,'
                    u'我們會在有更新的時候通知您!'),
            Message(u'在等待的同時,'
                    u'您可以先看看之前的集數喲!')
        ] + render_episodes(episodes, variables))

    if content_config['mode'] == 'unsubscribe':
        event = variables['event']
        drama_id = event.value['drama_id']
        drama_info.unsubscribe(user_id, drama_id)

        return [Message(u'已成功取消訂閱')]

    if content_config['mode'] == 'get_history':
        event = variables['event']
        drama_id = event.value['drama_id']
        Memory.Set('last_query_drama_id', drama_id)
        from_episode = event.value['from_episode']
        backward = event.value['backward']
        episodes = drama_info.get_history(drama_id=drama_id,
                                          from_episode=from_episode,
                                          backward=backward)

        return render_episodes(episodes, variables)

    if content_config['mode'] == 'prompt':
        m = Message(u'你比較喜歡以下的什麼劇呢?')
        append_categories_to_quick_reply(m)
        return [m]

    country = content_config['mode'].replace('trending_', '')
    if content_config['mode'] == 'search':
        query_term = Resolve(content_config['query_term'], variables)
        dramas = drama_info.search(user_id, query_term, n_items)
        if dramas:
            if len(dramas) == 1:
                Memory.Set('last_query_drama_id', dramas[0].id)
            m = render_dramas(dramas)
            append_categories_to_quick_reply(m)
            return [m]
        m = Message(u'找不到耶!你可以換個關鍵字或試試熱門的類別:')
        append_categories_to_quick_reply(m)
        return [m]

    if content_config['mode'] == 'search_episode':
        if len(variables['matches']) == 3:
            dramas = drama_info.search(user_id, variables['matches'][1], 1)
            if dramas:
                Memory.Set('last_query_drama_id', dramas[0].id)

        drama_id = Memory.Get('last_query_drama_id')
        if drama_id:
            try:
                try:
                    serial_number = int(
                        Resolve(content_config['episode'], variables))
                except ValueError:
                    serial_number = convert_to_arabic_numbers(
                        Resolve(content_config['episode'], variables))
                episode = drama_info.get_episode(drama_id, serial_number)
            except Exception:
                return [Message('沒有這一集喔')]
            return render_episodes([episode], variables)
        else:
            return [Message('請先告訴我你要查的劇名')]

    m = render_dramas(drama_info.get_trending(user_id, country=country))
    append_categories_to_quick_reply(m)
    return [m]
Exemplo n.º 24
0
def render_episodes(episodes, variables):
    """Render cards given a list of episodes"""
    if not len(episodes):
        return [Message(u'沒有更多的集數可以看囉 :(')]

    m = Message()
    for ep in episodes:
        b = Message.Bubble(ep.drama_name + u'第 %d 集' % ep.serial_number,
                           image_url=CacheImage(ep.image_url),
                           subtitle=ep.description)

        b.add_button(
            Message.Button(Message.ButtonType.WEB_URL,
                           u'帶我去看',
                           url=TrackedURL(ep.link, 'WatchButton'),
                           variables=variables))
        b.add_button(
            Message.Button(Message.ButtonType.POSTBACK,
                           u'我想看前幾集',
                           payload=EventPayload(
                               'GET_HISTORY', {
                                   'drama_id': ep.drama_id,
                                   'from_episode': ep.serial_number,
                                   'backward': True,
                               })))
        m.add_bubble(b)

    m.add_quick_reply(Message.QuickReply(Message.QuickReplyType.TEXT, u'第1集'))
    m.add_quick_reply(Message.QuickReply(Message.QuickReplyType.TEXT, u'熱門韓劇'))
    m.add_quick_reply(Message.QuickReply(Message.QuickReplyType.TEXT, u'熱門日劇'))
    m.add_quick_reply(Message.QuickReply(Message.QuickReplyType.TEXT, u'熱門台劇'))
    m.add_quick_reply(Message.QuickReply(Message.QuickReplyType.TEXT, u'熱門陸劇'))
    m.add_quick_reply(Message.QuickReply(Message.QuickReplyType.TEXT, u'通知設定'))

    return [m]