Beispiel #1
0
class Community:
    """ Community is an extension of steem.commit.Commit class. It allows you to construct
    various community related `custom_json` operations, and commit them onto the blockchain.

    Args:
        community_name (str): Community to operate in.
        account_name (str): Account to perform actions with.
    """

    _id = 'com.steemit.community'
    _roles = PERMISSIONS.keys()
    _valid_settings = ['title', 'about', 'description', 'language', 'is_nsfw']

    def __init__(self, community_name: str, account_name: str):
        self.community = community_name
        self.account = account_name

    def create(self,
               community_type: str = 'public',
               admins: Union[str, list] = None):
        """ Create a new community.

        This method will upgrade an existing STEEM account into a new community.

        Args:
            community_type: Can be **public** (default) or **restricted**.
            admins: list of users who will be community Admins.
             If left empty, the owner will be assigned as a single admin.
        """
        # validate account and community name
        #Account(self.account)
        assert self.community == self.account, 'Account name and community name need to be the same'

        if is_community(self.community):
            raise NameError('community %s already exists.' % self.community)

        if isinstance(admins, str):
            admins = [admins]
        if not admins:
            admins = [self.community]

        op = self._op(action='create', type=community_type, admins=admins)
        return self._commit(op)

    def update_settings(self, **settings):
        """ Update community settings / metadata. """
        # sanitize the settings to valid keys
        settings = {
            k: v
            for k, v in settings.items() if k in self._valid_settings
        }
        assert self._has_permissions(
            'update_settings'), 'Insufficient Community Permissions'
        op = self._op(action='update_settings', settings=settings)
        return self._commit(op)

    def add_users(self, account_names: Union[str, list], role: str):
        """ Add user to the community in the specified role.

        Args:
            account_names (str, list): accounts to add to the community.
            role (str): Roles to apply. Can be admin, moderator or poster.

        """
        return self._add_or_remove_users(account_names, role, 'add')

    def remove_users(self, account_names: Union[str, list], role: str):
        """ Opposite of `add_user`. """
        return self._add_or_remove_users(account_names, role, 'remove')

    def _add_or_remove_users(self, account_names: Union[str, list], role: str,
                             action: str):
        """ Implementation for adding/removing users to communities under various roles. """
        if isinstance(account_names, str):
            account_names = [account_names]

        if role not in self._roles:
            raise ValueError('Invalid role `%s`. options: %s' %
                             (role, ', '.join(self._roles)))

        action_name = '{0}_{1}s'.format(action, role)
        assert self._has_permissions(
            action_name), 'Insufficient Community Permissions'
        op = self._op(action=action_name, accounts=account_names)
        return self._commit(op)

    def set_user_title(self, account_name: str, title: str):
        """ Set a title for given user. """
        # todo: check permissions.
        # can you asssign title to self?
        # can mod/admin assign title to someone else?
        op = self._op(action='set_user_title',
                      account=account_name,
                      title=title)
        return self._commit(op)

    def mute_user(self, account_name: str):
        """ Mute user """
        assert self._has_permissions(
            'mute_user'), 'Insufficient Community Permissions'
        op = self._op(action='mute_user', account=account_name)
        return self._commit(op)

    def unmute_user(self, account_name: str):
        """ Un-Mute user """
        assert self._has_permissions(
            'unmute_user'), 'Insufficient Community Permissions'
        op = self._op(action='unmute_user', account=account_name)
        return self._commit(op)

    def mute_post(self, author: str, permlink: str, notes: str):
        """ Mute post """
        assert self._has_permissions(
            'mute_post'), 'Insufficient Community Permissions'
        op = self._op(action='mute_post',
                      author=author,
                      permlink=permlink,
                      notes=notes)
        return self._commit(op)

    def unmute_post(self, author: str, permlink: str, notes: str):
        """ Un-Mute post """
        assert self._has_permissions(
            'unmute_post'), 'Insufficient Community Permissions'
        op = self._op(action='unmute_post',
                      author=author,
                      permlink=permlink,
                      notes=notes)
        return self._commit(op)

    def pin_post(self, author: str, permlink: str):
        """ Pin post """
        assert self._has_permissions(
            'pin_post'), 'Insufficient Community Permissions'
        op = self._op(action='pin_post', author=author, permlink=permlink)
        return self._commit(op)

    def unpin_post(self, author: str, permlink: str):
        """ Un-Pin post """
        assert self._has_permissions(
            'unpin_post'), 'Insufficient Community Permissions'
        op = self._op(action='unpin_post', author=author, permlink=permlink)
        return self._commit(op)

    def flag_post(self, author: str, permlink: str, comment: str):
        """ Flag post """
        assert self._has_permissions(
            'flag_post'), 'Insufficient Community Permissions'
        op = self._op(action='flag_post',
                      author=author,
                      permlink=permlink,
                      comment=comment)
        return self._commit(op)

    def _commit(self, community_op: Union[list, str]):
        """ Construct and commit a community *custom_json* operation to the blockchain. """
        if isinstance(community_op, str):
            community_op = json.loads(community_op)

        op = {
            'json': community_op,
            'required_auths': [],
            'required_posting_auths': [self.account],
            'id': Community._id
        }
        return op

    def _op(self, action: str, **params):
        """ Generate a standard data structure for community *custom_json* operations. """
        return [action, {'community': self.community, **params}]

    def _has_permissions(self, action: str, account_name=None) -> bool:
        """ Check if this account has the right to perform this action within the community.
        Should be called as helper in most methods.
        """
        if not account_name:
            account_name = self.account

        return is_permitted(account_name, self.community, action)
Beispiel #2
0
def process_json_community_op(account, op_json, date):
    """Validates community op and apply state changes to db."""
    #pylint: disable=line-too-long
    cmd_name, cmd_op = op_json  # ['flagPost', {community: '', author: '', ...}]

    commands = list(flatten(PERMISSIONS.values()))
    if cmd_name not in commands:
        return

    print("community op from {} @ {} -- {}".format(account, date, op_json))

    community = cmd_op['community']
    community_exists = is_community(community)

    # special case: community creation. TODO: does this require ACTIVE auth? or POSTING will suffice?
    if cmd_name == 'create' and not community_exists:
        if account != community:  # only the OWNER may create
            return

        ctype = cmd_op['type']  # restricted, open-comment, public
        # INSERT INTO hive_communities (account, name, about, description, lang, is_nsfw, is_private, created_at)
        # VALUES ('%s', '%s', '%s', '%s', '%s', %d, %d, '%s')" % [account, name, about, description, lang, is_nsfw ? 1 : 0, is_private ? 1 : 0, block_date]
        # INSERT ADMINS---

    # validate permissions
    if not community_exists or not is_permitted(account, community, cmd_name):
        return

    # If command references a post, ensure it's valid
    post_id, depth = Posts.get_id_and_depth(cmd_op.get('author'),
                                            cmd_op.get('permlink'))
    if not post_id:
        return

    # If command references an account, ensure it's valid
    account_id = Accounts.get_id(cmd_op.get('account'))

    # If command references a list of accounts, ensure they are valid
    account_ids = list(map(Accounts.get_id, cmd_op.get('accounts')))

    # ADMIN Actions
    # -------------
    if cmd_name == 'add_admins':
        assert account_ids
        # UPDATE hive_members SET is_admin = 1 WHERE account IN (%s) AND community = '%s'

    if cmd_name == 'remove_admins':
        assert account_ids
        # todo: validate at least one admin remains!!!
        # UPDATE hive_members SET is_admin = 0 WHERE account IN (%s) AND community = '%s'

    if cmd_name == 'add_mods':
        assert account_ids
        # UPDATE hive_members SET is_mod = 1 WHERE account IN (%s) AND community = '%s'

    if cmd_name == 'remove_mods':
        assert account_ids
        # UPDATE hive_members SET is_mod = 0 WHERE account IN (%s) AND community = '%s'

    # MOD USER Actions
    # ----------------
    if cmd_name == 'update_settings':
        # name, about, description, lang, is_nsfw
        # settings {bg_color, bg_color2, text_color}
        # UPDATE hive_communities SET .... WHERE community = '%s'
        assert account_id

    if cmd_name == 'add_posters':
        assert account_ids
        # UPDATE hive_members SET is_approved = 1 WHERE account IN (%s) AND community = '%s'

    if cmd_name == 'remove_posters':
        assert account_ids
        # UPDATE hive_members SET is_approved = 0 WHERE account IN (%s) AND community = '%s'

    if cmd_name == 'mute_user':
        assert account_id
        # UPDATE hive_members SET is_muted = 1 WHERE account = '%s' AND community = '%s'

    if cmd_name == 'unmute_user':
        assert account_id
        # UPDATE hive_members SET is_muted = 0 WHERE account = '%s' AND community = '%s'

    if cmd_name == 'set_user_title':
        assert account_id
        # UPDATE hive_members SET title = '%s' WHERE account = '%s' AND community = '%s'

    # MOD POST Actions
    # ----------------
    if cmd_name == 'mute_post':
        assert post_id
        # assert all([account_id, post_id])
        # UPDATE hive_posts SET is_muted = 1 WHERE community = '%s' AND author = '%s' AND permlink = '%s'

    if cmd_name == 'unmute_post':
        assert post_id
        # UPDATE hive_posts SET is_muted = 0 WHERE community = '%s' AND author = '%s' AND permlink = '%s'

    if cmd_name == 'pin_post':
        assert post_id
        # UPDATE hive_posts SET is_pinned = 1 WHERE community = '%s' AND author = '%s' AND permlink = '%s'

    if cmd_name == 'unpin_post':
        assert post_id
        # UPDATE hive_posts SET is_pinned = 0 WHERE community = '%s' AND author = '%s' AND permlink = '%s'

    # GUEST POST Actions
    # ------------------
    if cmd_name == 'flag_post':
        assert post_id
        # INSERT INTO hive_flags (account, community, author, permlink, comment, created_at) VALUES ()

    # track success (TODO: failures as well?)
    # INSERT INTO hive_modlog (account, community, action, created_at) VALUES  (account, community, json.inspect, block_date)
    return True