Ejemplo n.º 1
0
def social_feed_init():
    container = SkygearContainer(api_key=options.masterkey)

    container.send_action(
        'schema:create', {
            'record_types': {
                'user': {
                    'fields': [
                        {
                            'name': 'name',
                            'type': 'string',
                        },
                        {
                            'name': 'social_feed_fanout_policy',
                            'type': 'json',
                        },
                        {
                            'name': 'social_feed_fanout_policy_is_dirty',
                            'type': 'boolean',
                        },
                    ]
                }
            }
        })

    for record_type in SOCIAL_FEED_RECORD_TYPES:
        create_table_for_social_feed(container, record_type)

    with db.conn() as conn:
        sql = 'CREATE EXTENSION IF NOT EXISTS "uuid-ossp"'
        conn.execute(sql)
Ejemplo n.º 2
0
 def save(self) -> None:
     """
     Save the Message record to the database.
     """
     container = SkygearContainer(api_key=skyoptions.masterkey,
                                  user_id=current_user_id())
     container.send_action('record:save', {
         'database_id': '_public',
         'records': [serialize_record(self.record)],
         'atomic': True
     })
Ejemplo n.º 3
0
def _get_conversation(conversation_id):
    # conversation_id can be Reference, recordID or string
    if isinstance(conversation_id, Reference):
        conversation_id = conversation_id.recordID.key
    if isinstance(conversation_id, RecordID):
        conversation_id = conversation_id.key

    container = SkygearContainer(api_key=skyoptions.apikey)
    response = container.send_action(
        'record:query',
        {
            'database_id': '_public',
            'record_type': 'conversation',
            'limit': 1,
            'sort': [],
            'include': {},
            'count': False,
            'predicate': [
                'eq', {
                    '$type': 'keypath',
                    '$val': '_id'
                },
                conversation_id
            ]
        }
    )

    if 'error' in response:
        raise SkygearChatException(response['error'])

    if len(response['result']) == 0:
        raise SkygearChatException("no conversation found")

    return response['result'][0]
Ejemplo n.º 4
0
def _get_conversation(conversation_id):
    # conversation_id can be Reference, recordID or string
    if isinstance(conversation_id, Reference):
        conversation_id = conversation_id.recordID.key
    if isinstance(conversation_id, RecordID):
        conversation_id = conversation_id.key

    container = SkygearContainer(api_key=skygear_config.app.api_key)
    response = container.send_action(
        'record:query', {
            'database_id':
            '_public',
            'record_type':
            'conversation',
            'limit':
            1,
            'sort': [],
            'include': {},
            'count':
            False,
            'predicate':
            ['eq', {
                '$type': 'keypath',
                '$val': '_id'
            }, conversation_id]
        })

    if 'error' in response:
        raise SkygearChatException(response['error'])

    if len(response['result']) == 0:
        raise SkygearChatException("no conversation found")

    return response['result'][0]
Ejemplo n.º 5
0
def schema_add_key_verified_acl(flag_names):
    """
    Add field ACL to disallow owner from modifying verified flags.
    """
    container = SkygearContainer(api_key=skyoptions.masterkey)

    # Fetch the current field ACL. If no changes are required, we will
    # not try to update the field ACL.
    resp = container.send_action("schema:field_access:get", {},
                                 plugin_request=True)
    if "error" in resp:
        raise SkygearException.from_dict(resp["error"])

    # Create the new ACL settings. This is accomplished by first
    # copying the existing field ACLs, ignoring the entries we need
    # to enforce.
    new_acls = []
    for acl in resp['result']['access']:
        if acl['record_type'] == 'user' \
                and acl['record_field'] in flag_names \
                and acl['user_role'] == '_owner':
            continue
        new_acls.append(acl)

    for flag_name in flag_names:
        new_acls.append({
            'record_type': 'user',
            'record_field': flag_name,
            'user_role': '_owner',
            'writable': False,
            'readable': True,
            'comparable': True,
            'discoverable': True,
        })

    if not new_acls:
        return

    # Update the field ACL.
    resp = container.send_action("schema:field_access:update",
                                 {"access": new_acls},
                                 plugin_request=True)
    if "error" in resp:
        raise SkygearException.from_dict(resp["error"])
Ejemplo n.º 6
0
 def _send_multi(self, action, **payload):
     token = self._access_token()
     container = SkygearContainer(access_token=token)
     result = container.send_action(action, payload)
     if 'error' in result:
         raise SkygearException.from_dict(result['error'])
     elif 'result' in result and isinstance(result['result'], list):
         return result
     else:
         raise SkygearException('unexpected result', UnexpectedError)
Ejemplo n.º 7
0
def chat_plugin_init():
    container = SkygearContainer(api_key=options.masterkey)

    container.send_action("schema:create", {"record_types": {"user": {"fields": [{"name": "name", "type": "string"}]}}})

    container.send_action(
        "schema:create",
        {
            "record_types": {
                "conversation": {
                    "fields": [
                        {"name": "title", "type": "string"},
                        {"name": "admin_ids", "type": "json"},
                        {"name": "participant_ids", "type": "json"},
                        {"name": "is_direct_message", "type": "boolean"},
                    ]
                }
            }
        },
    )

    container.send_action(
        "schema:create",
        {
            "record_types": {
                "message": {
                    "fields": [
                        {"name": "attachment", "type": "asset"},
                        {"name": "body", "type": "string"},
                        {"name": "metadata", "type": "json"},
                        {"name": "conversation_id", "type": "ref(conversation)"},
                    ]
                }
            }
        },
    )

    container.send_action(
        "schema:create",
        {
            "record_types": {
                "user_conversation": {
                    "fields": [
                        {"name": "user", "type": "ref(user)"},
                        {"name": "conversation", "type": "ref(conversation)"},
                        {"name": "unread_count", "type": "number"},
                        {"name": "last_read_message", "type": "ref(message)"},
                    ]
                }
            }
        },
    )
Ejemplo n.º 8
0
    def save(self) -> None:
        """
        Save the collection of receipts to the database. This function
        does nothing if there is nothing in the collection.
        """
        if not len(self):
            return

        records_to_save = [
            serialize_record(receipt.record)
            for receipt in self
        ]

        container = SkygearContainer(api_key=skyoptions.masterkey,
                                     user_id=current_user_id())
        container.send_action('record:save', {
            'database_id': '_public',
            'records': records_to_save,
            'atomic': True
        })
Ejemplo n.º 9
0
def signup(user_id):
    container = SkygearContainer(
        api_key=os.getenv('API_KEY')
    )
    pw = hashlib.sha1(bytes(user_id + 'Aih2xoopho', 'utf8')).hexdigest()
    result = container.send_action('auth:signup', {
        'username': user_id,
        'password': pw
    })
    log.info(result)
    return result['id']
Ejemplo n.º 10
0
def get_token():
    global skygear_token
    if skygear_token is not None:
        return skygear_token

    container = SkygearContainer()
    try:
        resp = container.send_action('auth:login', {
            'username': os.getenv('SKYGEAR_BOT'),
            'password': os.getenv('SKYGEAR_BOT_PW')
        })
    except SkygearException:
        log.debug('New setup, registering')
        resp = container.send_action('auth:signup', {
            'username': os.getenv('SKYGEAR_BOT'),
            'password': os.getenv('SKYGEAR_BOT_PW')
        })
    finally:
        log.debug(resp)
        skygear_token = resp['result']['access_token']
    return skygear_token
Ejemplo n.º 11
0
def schema_add_key_verified_flags(flag_names):
    """
    Add the fields into Skygear DB user record.

    This function adds the specified fields into the user record schema. It
    is expected that all fields have boolean data type.
    """
    if not flag_names:
        return

    container = SkygearContainer(api_key=skyoptions.masterkey)

    # Fetch schema first. If no changes are required, we will not try
    # to update the schema.
    resp = container.send_action("schema:fetch", {}, plugin_request=True)
    if "error" in resp:
        raise SkygearException.from_dict(resp["error"])

    for field in resp['result']['record_types']['user']['fields']:
        if field['name'] in flag_names:
            flag_names.remove(field['name'])

    # `flag_names` now contain the list of fields to create. Proceed
    # to create the field list and save the new fields to user record
    # schema.
    fields = [{
        'name': flag_name,
        'type': 'boolean'
    } for flag_name in flag_names]

    resp = container.send_action(
        "schema:create", {"record_types": {
            'user': {
                'fields': fields
            }
        }},
        plugin_request=True)
    if "error" in resp:
        raise SkygearException.from_dict(resp["error"])
Ejemplo n.º 12
0
def save_user_record(user_record):
    """
    Save the user record to Skygear Record API.
    """
    container = SkygearContainer(api_key=skyoptions.masterkey)

    resp = container.send_action("record:save",
                                 {"records": [serialize_record(user_record)]},
                                 plugin_request=True)
    try:
        if "error" in resp:
            raise SkygearException.from_dict(resp["error"])
    except (ValueError, TypeError, KeyError):
        raise SkygearContainer("container.send_action is buggy")
Ejemplo n.º 13
0
 def _send_single(self, action, **payload):
     token = self._access_token()
     container = SkygearContainer(access_token=token)
     result = container.send_action(action, payload)
     if 'error' in result:
         raise SkygearException.from_dict(result['error'])
     elif 'result' in result and isinstance(result['result'], list) \
             and len(result['result']) > 0:
         first_result = result['result'][0]
         if first_result.get('_type', None) == 'error':
             raise SkygearException.from_dict(first_result)
         return first_result
     else:
         raise SkygearException('unexpected result', UnexpectedError)
Ejemplo n.º 14
0
def create_conversation(uid):
    container = SkygearContainer(
        api_key=os.getenv('MASTER_KEY'),
        user_id=uid
    )
    result = container.send_action('record:save', {
        'records': [{
            '_id': 'conversation/' + uid + CHAT_BOT_ID,
            'participant_ids': [uid, CHAT_BOT_ID],
            'is_direct_message': True
        }],
        'database_id': '_public'
    })
    log.info(result)
    return result['result'][0]['_id']
Ejemplo n.º 15
0
def create_message(cid, uid, body):
    container = SkygearContainer(
        api_key=os.getenv('MASTER_KEY'),
        user_id=uid
    )
    result = container.send_action('record:save', {
        'records': [{
            '_id': 'message/' + uuid.uuid4().urn[9:],
            'conversation_id': cid,
            'body': body 
        }],
        'database_id': '_private'
    })
    log.info(result)
    return result['result'][0]['_id']
Ejemplo n.º 16
0
def set_new_password(user_id, new_password):
    """
    Set the password of a user to a new password
    with auth:reset_password
    """
    container = SkygearContainer(api_key=skyoptions.masterkey)
    resp = container.send_action("auth:reset_password", {
        "auth_id": user_id,
        "password": new_password,
    },
                                 plugin_request=True)
    try:
        if "error" in resp:
            raise SkygearException.from_dict(resp["error"])
    except (ValueError, TypeError, KeyError):
        raise SkygearContainer("container.send_action is buggy")
Ejemplo n.º 17
0
def fetch_user_record(auth_id):
    """
    Fetch the user record from Skygear Record API. The returned value
    is a user record in Record class.
    """
    container = SkygearContainer(api_key=skyoptions.masterkey)

    resp = container.send_action("record:fetch",
                                 {"ids": ['user/{}'.format(auth_id)]},
                                 plugin_request=True)
    try:
        if "error" in resp:
            raise SkygearException.from_dict(resp["error"])
    except (ValueError, TypeError, KeyError):
        raise SkygearContainer("container.send_action is buggy")
    return deserialize_record(resp['result'][0])
Ejemplo n.º 18
0
 def chat_plugin_init(config):
     container = SkygearContainer(api_key=skyoptions.masterkey)
     container.send_action(
         'schema:create',
         {
             'record_types': {
                 'user': {
                     'fields': [
                         {'name': 'name', 'type': 'string'}
                     ]
                 },
                 'conversation': {
                     'fields': [
                         {
                             'name': 'title',
                             'type': 'string'
                         },
                         {
                             'name': 'admin_ids',
                             'type': 'json'
                         },
                         {
                             'name': 'participant_ids',
                             'type': 'json'
                         },
                         {
                             'name': 'participant_count',
                             'type': 'number'
                         },
                         {
                             'name': 'metadata',
                             'type': 'json'
                         },
                         {
                             'name': 'distinct_by_participants',
                             'type': 'boolean'
                         }
                     ]
                 }
             }
         },
         plugin_request=True
     )
     container.send_action(
         'schema:create',
         {
             'record_types': {
                 'message': {
                     'fields': [
                         {
                             'name': 'attachment',
                             'type': 'asset'
                         },
                         {
                             'name': 'body',
                             'type': 'string'
                         },
                         {
                             'name': 'metadata',
                             'type': 'json'
                         },
                         {
                             'name': 'conversation_id',
                             'type': 'ref(conversation)'
                         },
                         {
                             'name': 'conversation_status',
                             'type': 'string'
                         }
                     ]
                 }
             }
         },
         plugin_request=True
     )
     container.send_action(
         'schema:create',
         {
             'record_types': {
                 'user_conversation': {
                     'fields': [
                         {
                             'name': 'user',
                             'type': 'ref(user)'
                         },
                         {
                             'name': 'conversation',
                             'type': 'ref(conversation)'
                         },
                         {
                             'name': 'unread_count',
                             'type': 'number'
                         },
                         {
                             'name': 'last_read_message',
                             'type': 'ref(message)'
                         }
                     ]
                 },
                 'receipt': {
                     'fields': [
                         {
                             'name': 'user_id',
                             'type': 'ref(user)'
                         },
                         {
                             'name': 'message_id',
                             'type': 'ref(message)'
                         },
                         {
                             'name': 'read_at',
                             'type': 'datetime'
                         },
                         {
                             'name': 'delivered_at',
                             'type': 'datetime'
                         }
                     ]
                 },
                 'conversation': {
                     'fields': [
                         {
                             'name': 'last_message',
                             'type': 'ref(message)'
                         }
                     ]
                 }
             }
         },
         plugin_request=True
     )
Ejemplo n.º 19
0
    def fetch(cls, message_id: str):
        """
        Fetch the message from skygear.

        The conversation record is also fetched using eager load.
        """
        # FIXME checking should not be necessary, passing correct type
        # is the responsibility of the caller.
        # message_id can be Reference, recordID or string
        if isinstance(message_id, Reference):
            message_id = message_id.recordID.key
        if isinstance(message_id, RecordID):
            message_id = message_id.key
        if not isinstance(message_id, str):
            raise ValueError()

        container = SkygearContainer(api_key=skyoptions.masterkey,
                                     user_id=current_user_id())
        response = container.send_action(
            'record:query',
            {
                'database_id': '_union',
                'record_type': 'message',
                'limit': 1,
                'sort': [],
                'count': False,
                'predicate': [
                    'eq', {
                        '$type': 'keypath',
                        '$val': '_id'
                    },
                    message_id
                ]
            }
        )

        if 'error' in response:
            raise SkygearChatException(response['error'])

        if len(response['result']) == 0:
            raise SkygearChatException('no messages found',
                                       code=ResourceNotFound)

        obj = cls()
        messageDict = response['result'][0]
        obj.record = deserialize_record(messageDict)
        # Conversation is in publicDB, do cannot transient include
        print(obj.record['conversation_id'].recordID.key)
        response = container.send_action(
            'record:query',
            {
                'database_id': '_public',
                'record_type': 'conversation',
                'limit': 1,
                'sort': [],
                'count': False,
                'predicate': [
                    'eq', {
                        '$type': 'keypath',
                        '$val': '_id'
                    },
                    obj.record['conversation_id'].recordID.key
                ]
            }
        )
        if len(response['result']) == 0:
            raise SkygearChatException("no conversation found")
        conversationDict = response['result'][0]
        obj.conversationRecord = deserialize_record(conversationDict)
        return obj
Ejemplo n.º 20
0
class OurskyBot():
    questions = {
        'chat': [
            ['What free chat?, email [email protected]']
        ],
        'web_or_app': [
            ['Can you briefly describe your idea?'],
            ['Which email shall our Project Consultant reach you at?'],
            [
                'Great! Thank you and we will be in touch shortly!',
                {
                    'template_type':'generic',
                    'elements': [{
                        'title': 'Learn more about Oursky',
                        'subtitle': '',
                        'image_url': 'https://oursky.com/img/logo-square.png',
                        'buttons': [{
                            'type': 'web_url',
                            'url': 'https://oursky.com/prototype',
                            'title': 'View'
                        }]
                    }]
                }
            ]
        ],
        'message_bot': [
            ['Interesting! Which company / business are you from?'],
            ['How do you plan to use the Messenger Bot?'],
            ['Interesting! Which email shall we reach you?'],
            [
                'Thanks! We will be in touch shortly!',
                {
                    'template_type':'generic',
                    'elements': [{
                        'title': 'Learn more about Oursky',
                        'subtitle': '',
                        'image_url': 'https://oursky.com/img/logo-square.png',
                        'buttons': [{
                            'type': 'web_url',
                            'url': 'https://oursky.com/',
                            'title': 'View'
                        }]
                    }]
                }
            ]
        ],
        'other_enquiry': [
            ['Can you briefly describe your needs?'],
            ['What is your company name?'],
            ['Which email shall our Project Consultant reach you at?'],
            [
                'Great! Thank you and we will be in touch shortly!',
                {
                    'template_type':'generic',
                    'elements': [{
                        'title': 'Learn more about Oursky',
                        'subtitle': '',
                        'image_url': 'https://oursky.com/img/logo-square.png',
                        'buttons': [{
                            'type': 'web_url',
                            'url': 'https://oursky.com/',
                            'title': 'View'
                        }]
                    }]
                }
            ]
        ]
    }

    def __init__(self, user):
        self.what = 'chat'
        self.step = 0
        self.user = user
        self.container = SkygearContainer(access_token=get_token())
        response = self.container.send_action('record:query', {
            'record_type': 'fb_user',
            'predicate': [
                'eq',
                {'$type': 'keypath', '$val': '_id'},
                user 
            ]
        })
        log.debug(response)
        result = response['result']
        try:
            user = result[0]
        except IndexError:
            return
        else:
            if user:
                self.step = user['step']
                self.what = user['enquiry_topic']

    def client_wants(self, what):
        if self.what != what:
            self.what = what
            self.step = 0
            self.upsert_fb_user()

    def upsert_fb_user(self):
        self.container.send_action('record:save', {'records': [{
            '_id': 'fb_user/{}'.format(self.user),
            'enquiry_topic': self.what,
            'step': self.step
        }]})

    def listen(self, message):
        # Save to skygear
        self.step = self.step + 1
        self.upsert_fb_user()
        self.container.send_action('record:save', {'records': [{
            '_id': 'fb_message/{}'.format(uuid.uuid4()),
            'enquiry_topic': self.what,
            'message': message
        }]})

    def speak(self): 
        log.debug('Speaking %s %s', self.what, self.step)
        try:
            return self.questions[self.what][self.step]
        except IndexError as e:
            log.warn(e)
            return ['Please email [email protected] for follow up']
Ejemplo n.º 21
0
 def chat_plugin_init(config):
     container = SkygearContainer(api_key=skyoptions.masterkey)
     container.send_action('schema:create', {
         'record_types': {
             'user': {
                 'fields': [{
                     'name': 'name',
                     'type': 'string'
                 }]
             },
             'conversation': {
                 'fields': [{
                     'name': 'title',
                     'type': 'string'
                 }, {
                     'name': 'admin_ids',
                     'type': 'json'
                 }, {
                     'name': 'participant_ids',
                     'type': 'json'
                 }, {
                     'name': 'participant_count',
                     'type': 'number'
                 }, {
                     'name': 'metadata',
                     'type': 'json'
                 }, {
                     'name': 'distinct_by_participants',
                     'type': 'boolean'
                 }]
             }
         }
     },
                           plugin_request=True)
     container.send_action('schema:create', {
         'record_types': {
             'message': {
                 'fields': [{
                     'name': 'attachment',
                     'type': 'asset'
                 }, {
                     'name': 'body',
                     'type': 'string'
                 }, {
                     'name': 'metadata',
                     'type': 'json'
                 }, {
                     'name': 'conversation_id',
                     'type': 'ref(conversation)'
                 }, {
                     'name': 'conversation_status',
                     'type': 'string'
                 }]
             }
         }
     },
                           plugin_request=True)
     container.send_action('schema:create', {
         'record_types': {
             'user_conversation': {
                 'fields': [{
                     'name': 'user',
                     'type': 'ref(user)'
                 }, {
                     'name': 'conversation',
                     'type': 'ref(conversation)'
                 }, {
                     'name': 'unread_count',
                     'type': 'number'
                 }, {
                     'name': 'last_read_message',
                     'type': 'ref(message)'
                 }]
             },
             'receipt': {
                 'fields': [{
                     'name': 'user_id',
                     'type': 'ref(user)'
                 }, {
                     'name': 'message_id',
                     'type': 'ref(message)'
                 }, {
                     'name': 'read_at',
                     'type': 'datetime'
                 }, {
                     'name': 'delivered_at',
                     'type': 'datetime'
                 }]
             },
             'conversation': {
                 'fields': [{
                     'name': 'last_message',
                     'type': 'ref(message)'
                 }]
             }
         }
     },
                           plugin_request=True)
Ejemplo n.º 22
0
def chat_plugin_init():
    container = SkygearContainer(api_key=options.masterkey)

    container.send_action('schema:create', {
        'record_types': {
            'user': {
                'fields': [{
                    'name': 'name',
                    'type': 'string'
                }]
            }
        }
    })

    container.send_action(
        'schema:create', {
            'record_types': {
                'conversation': {
                    'fields': [{
                        'name': 'title',
                        'type': 'string'
                    }, {
                        'name': 'admin_ids',
                        'type': 'json'
                    }, {
                        'name': 'participant_ids',
                        'type': 'json'
                    }, {
                        'name': 'is_direct_message',
                        'type': 'boolean'
                    }]
                }
            }
        })

    container.send_action(
        'schema:create', {
            'record_types': {
                'message': {
                    'fields': [{
                        'name': 'attachment',
                        'type': 'asset'
                    }, {
                        'name': 'body',
                        'type': 'string'
                    }, {
                        'name': 'metadata',
                        'type': 'json'
                    }, {
                        'name': 'conversation_id',
                        'type': 'ref(conversation)'
                    }]
                }
            }
        })

    container.send_action(
        'schema:create', {
            'record_types': {
                'user_conversation': {
                    'fields': [{
                        'name': 'user',
                        'type': 'ref(user)'
                    }, {
                        'name': 'conversation',
                        'type': 'ref(conversation)'
                    }, {
                        'name': 'unread_count',
                        'type': 'number'
                    }, {
                        'name': 'last_read_message',
                        'type': 'ref(message)'
                    }]
                }
            }
        })