Beispiel #1
0
def check_update(push: bool = False):
    """
    Check for new release

    Args:
        push: whether to push out notifications if an update is found

    Returns:

        .. code-block:: guess

            {
                'url' : str,
                'tag' : str
                'changes' : str,
            }

        or ``null``

    |async command|

    .. seealso::

        :func:`.get_changelog` -- when a new update is found, its changelog is immediately available here

    """

    upd = meta_cmd.CheckUpdate(AsyncService.generic).run(force=True, push=push)
    return message.Identity('update', upd)
Beispiel #2
0
def get_changelog():
    """
    Get the changelog in markdown formatted text
    The changelog returned is for the current release or a new update

    Returns:

        .. code-block:: guess

            {
                'version': str,
                'changes': str
            }

    .. seealso::

        :func:`.check_update`

    """

    ch = {'version': '', 'changes': ''}
    lr = constants.internaldb.latest_release.get(None)
    if lr:
        ch['changes'] = lr.get("changes", "")
        ch['version'] = lr.get("tag", "")

    return message.Identity("changelog", ch)
Beispiel #3
0
def get_similar(item_type: enums.ItemType = enums.ItemType.Gallery,
                item_id: int = 0,
                limit=10):
    """
    Get similar items

    Args:
        item_type: possible items are :py:attr:`.ItemType.Gallery`
        item_id: id of item
        limit: amount of items

    Returns:
        .. code-block:: guess

            [
                item message object,
                ...
            ]

    |async command|
    """
    item_type = enums.ItemType.get(item_type)
    db_msg, db_model = item_type._msg_and_model((enums.ItemType.Gallery, ))
    c = gallery_cmd.SimilarGallery()
    services.AsyncService.generic.add_command(
        c,
        functools.partial(_get_similar, {
            'limit': limit,
            'db_model': db_model,
            'db_msg': db_msg
        }))
    return message.Identity('command', c.start(item_id))
Beispiel #4
0
def scan_galleries(path: str, scan_options: dict = {}):
    """
    Scan for galleries in the given directory/archive

    Args:
        path: path to directory/archive that exists on this system
        scan_options: options to apply to the scanning process, see :ref:`Settings` for available scanning options

    Returns:
        .. code-block:: guess

            {
                'command_id': int,
                'view_id': int
            }

    |async command|

    |temp view|
    """
    path = io_cmd.CoreFS(path)
    if not path.exists:
        raise exceptions.CoreError(
            utils.this_function(),
            f"Path does not exists on this system: '{path.path}'")

    view_id = next(constants.general_counter)
    cmd_id = gallery_cmd.ScanGallery(services.AsyncService.generic).run(
        path, scan_options, view_id=view_id)

    return message.Identity('data', {'command_id': cmd_id, 'view_id': view_id})
Beispiel #5
0
def new_item(item_type: enums.ItemType = enums.ItemType.Gallery,
             item: dict = {},
             options: dict = {}):
    """
    Create a new item and add it to the database

    Args:
        item_type: type of item to create
        item: item messeage object

    Returns:
        []

    |async command|

    """

    if not item:
        raise exceptions.APIError(utils.this_function(),
                                  "item must be a message object")
    if item.get('id', False) and not constants.dev:
        raise exceptions.APIError(utils.this_function(),
                                  "cannot create item with an id")

    item_type = enums.ItemType.get(item_type)
    db_msg, db_model = item_type._msg_and_model()

    db_obj = db_msg.from_json(item)

    cmd_id = database_cmd.AddItem(services.AsyncService.generic).run(
        db_obj, options=options)
    return message.Identity('command_id', cmd_id)
Beispiel #6
0
def get_command_value(command_ids: list):
    """
    Get the returned command value

    Args:
        command_ids: list of command ids

    Returns:
        ```
        { command_id : value }
        ```

    """

    _command_msg(command_ids)

    values = {}

    for i in command_ids:
        cmd = Service.get_command(i)
        if cmd.state not in (command.CommandState.finished, command.CommandState.stopped):
            if cmd.state == command.CommandState.failed:
                raise exceptions.CommandError(utils.this_function(), "Command with ID '{}' has failed".format(i))
            raise exceptions.CommandError(utils.this_function(),
                                          "Command with ID '{}' has not finished running".format(i))

        if isinstance(cmd.value, message.CoreMessage):
            values[i] = cmd.value.json_friendly(include_key=False)
        else:
            values[i] = cmd.value
        if constants.debug:
            cmd._log_stats(arrow.now())

    return message.Identity('command_value', values)
Beispiel #7
0
def get_translations(locale: str = None):
    """
    Get all translations for given locale

    You can find more about translations :ref:`here <Translations>`.

    Args:
        locale: locale to get translations from (will override default locale)

    Returns:
        .. code-block:: guess

            {
                'namespace.translation_id' : string
            }

    .. seealso::

        :func:`.get_locales`
    """
    trs = {}
    locale = helpers._get_locale(locale).lower()
    container = i18n.translations.container
    if locale in container:
        trs = container[locale].copy()
    else:
        try:
            translate("general.locale")
            trs = container[locale].copy()
        except exceptions.APIError:
            pass
    return message.Identity("translations", trs)
Beispiel #8
0
def get_view_count(item_type: enums.ItemType=enums.ItemType.Gallery,
                   item_id: int = None,
                   related_type: enums.ItemType = None,
                   search_query: str = "",
                   search_options: dict = {},
                   filter_id: int = None,
                   view_filter: enums.ViewType = enums.ViewType.Library):
    """
    Get count of items in view

    Args:
        item_type: possible items are :py:attr:`.ItemType.Gallery`, :py:attr:`.ItemType.Collection`, :py:attr:`.ItemType.Grouping`
        search_query: filter item by search terms
        search_options: options to apply when filtering, see :ref:`Settings` for available search options
        filter_id: current :py:attr:`.ItemType.GalleryFilter` item id
        view_filter: type of view, set ``None`` to not apply any filter
        related_type: child item
        item_id: id of parent item

    Returns:
        .. code-block:: guess

            {
                'count' : int
            }
    """
    view_filter, item_type, db_msg, db_model, model_ids, filter_op, join_exp, metatag_name = _view_helper(
        item_type, search_query, filter_id, view_filter, item_id, related_type, search_options)

    return message.Identity('count', {'count': database_cmd.GetModelItems().run(
        db_model, model_ids, filter=filter_op, join=join_exp, count=True)})
Beispiel #9
0
def update_item(item_type: enums.ItemType = enums.ItemType.Gallery,
                item: dict = {},
                options: dict = {}):
    """
    Update an existing item

    Args:
        item_type: type of item to create
        item: item messeage object

    Returns:
        bool indicating whether item was updated

    """

    if not item:
        raise exceptions.APIError(utils.this_function(),
                                  "Item must be a message object")
    if not item.get('id'):
        raise exceptions.APIError(utils.this_function(),
                                  "Item must have a valid id")

    item_type = enums.ItemType.get(item_type)
    db_msg, db_model = item_type._msg_and_model()

    db_obj = db_msg.from_json(item,
                              ignore_empty=False,
                              skip_updating_existing=False)

    status = database_cmd.UpdateItem().main(db_obj, options=options)
    return message.Identity('status', status)
Beispiel #10
0
def submit_temporary_view(view_type: enums.TemporaryViewType = enums.TemporaryViewType.GalleryAddition,
                          view_id: int = None,):
    """
    not ready yet...

    Args:
        view_type: type of temporary view
        view_id: id of a specific view
    Returns:
        []

    |async command|

    """
    view_type = enums.TemporaryViewType.get(view_type)

    cmd_id = None

    if view_type == enums.TemporaryViewType.GalleryAddition:
        c = constants.store.galleryfs_addition.get({})
        if view_id:
            c = list(c.get(view_id, tuple()))
        else:
            c = list(itertools.chain(*c.values()))
        cmd_id = database_cmd.AddItem(services.AsyncService.generic).run(c)

    return message.Identity('command_id', cmd_id)
Beispiel #11
0
def get_related_count(item_type: enums.ItemType = enums.ItemType.Gallery,
                      item_id: int = 0,
                      related_type: enums.ItemType = enums.ItemType.Page):
    """
    Get count of items related to given item

    Args:
        item_type: parent item
        item_id: id of parent item
        related_type: child item

    Returns:
        ```
        { 'id': int, 'count': int }
        ```
    """
    item_type = enums.ItemType.get(item_type)
    related_type = enums.ItemType.get(related_type)

    _, parent_model = item_type._msg_and_model()
    child_msg, child_model = related_type._msg_and_model()

    col = db.relationship_column(parent_model, child_model)
    if not col:
        raise exceptions.APIError(
            utils.this_function(),
            "{} has no relationship with {}".format(related_type, item_type))

    s = constants.db_session()
    count = s.query(
        child_model.id).join(col).filter(parent_model.id == item_id).count()
    return message.Identity('count', {'id': item_id, 'count': count})
Beispiel #12
0
def get_view_count(item_type: enums.ItemType = enums.ItemType.Gallery,
                   search_query: str = "",
                   filter_id: int = None,
                   view_filter: enums.ViewType = enums.ViewType.Library):
    """
    Get count of items in view

    Args:
        item_type: possible items are :py:attr:`.ItemType.Gallery`, :py:attr:`.ItemType.Collection`, :py:attr:`.ItemType.Grouping`
        search_query: filter item by search terms
        filter_id: current filter list id
        view_filter: ...

    Returns:
        ```
        { 'count': int }
        ```
    """

    view_filter = enums.ViewType.get(view_filter)
    item_type = enums.ItemType.get(item_type)

    db_msg, db_model = item_type._msg_and_model(
        (enums.ItemType.Gallery, enums.ItemType.Collection,
         enums.ItemType.Grouping))

    model_ids = search_cmd.ModelFilter().run(db_model, search_query)

    return message.Identity('count', {'count': len(model_ids)})
Beispiel #13
0
def get_common_tags(item_type: enums.ItemType = enums.ItemType.Collection,
                    item_id: int = 0,
                    limit: int = 10):
    """
    Get the most common tags for item

    Args:
        item_type: possible items are :attr:`.ItemType.Artist`, :attr:`.ItemType.Grouping`, :attr:`.ItemType.Collection`
        item_id: id of item to fetch tags for
        limit: limit amount of tags returned

    Returns:
        .. code-block:: guess

            {
                namespace : [ tag message object, ...],
                ...
            }
    """
    item_type = enums.ItemType.get(item_type)

    _, db_item = item_type._msg_and_model(
        (enums.ItemType.Artist, enums.ItemType.Collection,
         enums.ItemType.Grouping))

    nstags = database_cmd.MostCommonTags().run(db_item, item_id, limit)
    msg = _contruct_tags_msg(nstags)

    return message.Identity('tags', msg)
Beispiel #14
0
def translate(t_id: str,
              locale: str = None,
              default: str = None,
              placeholder: str = {},
              count: int = None):
    """
    Get a translation by translation id.
    Raises error if a default value was not provided and no translation was found.

    You can find more about translations :ref:`here <Translations>`.

    Args:
        t_id: translation id
        locale: locale to get translations from (will override default locale)
        default: default text when no translation was found
        placeholder: ?
        count: pluralization

    Returns:
        string

    .. seealso::

        :func:`.get_locales`
    """
    kwargs = {}
    trs = default

    kwargs["locale"] = helpers._get_locale(locale).lower()

    if placeholder:
        kwargs.update(placeholder),
    if count is not None:
        kwargs["count"] = count
    if default:
        kwargs["default"] = default

    if not t_id and default is None:
        raise exceptions.APIError(utils.this_function(),
                                  "Invalid translation id: {}".format(t_id))
    elif t_id:
        try:
            trs = i18n.t(t_id, **kwargs)
        except KeyError as e:
            if default is None:
                raise exceptions.APIError(
                    utils.this_function(),
                    "Translation id '{}' not found".format(t_id))

        except i18n.loaders.loader.I18nFileLoadError as e:
            if default is None:
                log.exception(
                    "Failed to load translation file '{}' with key '{}'".
                    format(
                        locale if locale else config.translation_locale.value,
                        t_id))
                raise exceptions.APIError(
                    utils.this_function(),
                    "Failed to load translation file: {}".format(e.args))
    return message.Identity("translation", trs)
Beispiel #15
0
def get_tags(item_type: enums.ItemType = enums.ItemType.Gallery,
             item_id: int = 0,
             raw: bool = False):
    """
    Get tags for item

    Args:
        item_type: possible items are :attr:`.ItemType.Gallery`, :attr:`.ItemType.Page`,
            :attr:`.ItemType.Grouping`, :attr:`.ItemType.Collection`
        item_id: id of item to fetch tags for
        raw: if true, tags from descendant ItemType's will not be included
            (this only makes sense when ItemType is :attr:`.ItemType.Gallery`)

    Returns:
        ```
        { namespace : list of tag message objects }
        ```
    """

    item_type = enums.ItemType.get(item_type)

    _, db_item = item_type._msg_and_model(
        (enums.ItemType.Gallery, enums.ItemType.Collection,
         enums.ItemType.Grouping, enums.ItemType.Page))

    db_obj = database_cmd.GetModelItemByID().run(db_item, {item_id})
    if db_obj:
        db_obj = db_obj[0]

    nstags = []
    if db_obj:
        g_objs = []
        if issubclass(db_item, db.TaggableMixin):
            nstags = db_obj.tags.all()
            if not raw and isinstance(db_obj, db.Gallery):
                g_objs.append(db_obj)
        else:
            for g in db_obj.galleries.all():
                nstags.extend(g.tags.all())
                if not raw:
                    g_objs.append(g)

        for g_obj in g_objs:
            for p in g_obj.pages.all():  # TODO: we only need tags
                nstags.extend(p.tags.all())

    msg = {}
    _msg = {}
    for nstag in nstags:
        ns = nstag.namespace.name
        if ns not in msg:
            msg[ns] = []
            _msg[ns] = []

        if nstag.tag.name not in _msg[ns]:
            msg[ns].append(
                message.Tag(nstag.tag, nstag).json_friendly(include_key=False))
            _msg[ns].append(nstag.tag.name)

    return message.Identity('tags', msg)
Beispiel #16
0
def search_tags(
    search_query: str = "",
    search_options: dict = {},
    only_namespace: bool = False,
    only_tag: bool = False,
    sort_by: enums.ItemSort = None,
    sort_desc: bool = False,
    limit: int = 100,
    offset: int = None,
):
    """
    Search for tags

    Args:
        search_query: search string
        search_options: options to apply when filtering, see :ref:`Settings` for available search options
        only_namespace: only search for matching namespace <not implemented yet>
        only_tag: only search for matching tag <not implemented yet>
        sort_by: either a :py:class:`.ItemSort` or a sort index
        sort_desc: order descending (default is ascending)
        limit: limit the amount of items returned
        offset: offset the results by n items

    Returns:
        .. code-block:: guess

            {
                namespace : [ tag message object, ...],
                ...
            }
    """
    if search_options:
        search_option_names = [
            x.name for x in search_cmd._get_search_options()
        ]
        for n in search_options:
            if n not in search_option_names:
                raise exceptions.APIError(
                    utils.this_function(),
                    "Invalid search option name '{}'".format(n))

    db_model = db.NamespaceTags
    model_ids = search_cmd.ModelFilter().run(db_model, search_query,
                                             search_options)

    order_exp, group_exp, join_exp = helpers._sort_helper(
        sort_by, sort_desc, db_model)

    items = database_cmd.GetModelItems().run(db_model,
                                             model_ids,
                                             limit=limit,
                                             offset=offset,
                                             join=join_exp,
                                             order_by=order_exp,
                                             group_by=group_exp)

    msg = _contruct_tags_msg(items)

    return message.Identity('tags', msg)
Beispiel #17
0
def restart_application():
    """
    Restart the application

    Returns:
        This function will not return
    """
    meta_cmd.RestartApplication().run()
    return message.Identity('status', True)
Beispiel #18
0
def reply_notification(msg_id: int, action_values: dict):
    """
    Not ready yet...
    """
    s = False
    if constants.notification:
        constants.notification.reply(msg_id, action_values)
        s = True
    return message.Identity("status", s)
Beispiel #19
0
def get_notification(scope=None, msg_id: int = None, expired: bool = False):
    """
    Not ready yet...
    """
    msg = None
    if constants.notification:
        msg = constants.notification._fetch(scope=scope, expired=expired)

    return msg if msg else message.Identity("notification", msg)
Beispiel #20
0
def shutdown_application():
    """
    Shutdown the application

    Returns:
        This function will not return
    """
    meta_cmd.ShutdownApplication().run()
    return message.Identity('status', True)
Beispiel #21
0
def get_locales():
    """
    Retrieve available translation locales

    Returns:

        .. code-block:: guess

            {
                str : {
                            'locale' : str
                            'namespaces': [str, ...]
                        }
            }

    .. seealso::

        :func:`.translate`
    """

    if constants.translations is None:
        trs_dict = {}
        for f in os.scandir(constants.dir_translations):
            if not f.is_file or not f.name.endswith(".yaml"):
                continue
            n = f.name.split(".")
            if len(n) == 3:
                t_locale, t_ns, _ = n
                l_dict = trs_dict.setdefault(t_locale, {})
                if 'locale' not in l_dict:
                    t_general = "{}.general.yaml".format(t_locale)
                    t_general_path = os.path.join(constants.dir_translations,
                                                  t_general)
                    if not os.path.exists(t_general_path):
                        continue
                    try:
                        with open(t_general_path, "r", encoding="utf-8") as rf:
                            f_dict = yaml.safe_load(rf)
                            if 'locale' in f_dict:
                                l_dict['locale'] = f_dict['locale']
                    except yaml.YAMLError as e:
                        log.w(
                            "Failed to load translation file {}:".format(
                                t_general), e)
                        continue

                l_dict.setdefault('namespaces', []).append(t_ns)
        constants.translations = trs_dict

    d = {}
    for a, b in constants.translations.items():
        if 'locale' not in b:
            continue
        d[a] = b

    return message.Identity("locales", d)
Beispiel #22
0
def get_version():
    """
    Get version of components: 'core', 'db' and 'torrent'

    Returns:
        a dict of component: list of major, minor, patch
    """
    vs = dict(core=list(constants.version),
              db=list(constants.version_db),
              torrent=(0, 0, 0))
    return message.Identity("version", vs)
Beispiel #23
0
def get_tags(item_type: enums.ItemType = enums.ItemType.Gallery,
             item_id: int = 0,
             raw: bool = False):
    """
    Get tags for item

    Args:
        item_type: possible items are :attr:`.ItemType.Gallery`, :attr:`.ItemType.Page`,
            :attr:`.ItemType.Grouping`, :attr:`.ItemType.Collection`
        item_id: id of item to fetch tags for
        raw: if true, tags from descendant ItemType's will not be included
            (this only makes sense when ItemType is :attr:`.ItemType.Gallery`)

    Returns:
        .. code-block:: guess

            {
                namespace : [ tag message object, ...],
                ...
            }
    """
    if not item_id:
        raise exceptions.APIError(utils.this_function(), "item_id must be a valid item id")

    item_type = enums.ItemType.get(item_type)

    _, db_item = item_type._msg_and_model(
        (enums.ItemType.Gallery, enums.ItemType.Collection, enums.ItemType.Grouping, enums.ItemType.Page))

    db_obj = database_cmd.GetModelItems().run(db_item, {item_id})
    if db_obj:
        db_obj = db_obj[0]

    nstags = []
    if db_obj:
        g_objs = []
        if issubclass(db_item, db.TaggableMixin):
            nstags = db_obj.tags.all()
            if not raw and isinstance(db_obj, db.Gallery):
                g_objs.append(db_obj)
        else:
            for g in db_obj.galleries.all():
                nstags.extend(g.tags.all())
                if not raw:
                    g_objs.append(g)

        for g_obj in g_objs:
            for p in g_obj.pages.all():  # TODO: we only need tags
                nstags.extend(p.tags.all())

    msg = _contruct_tags_msg(nstags)

    return message.Identity('tags', msg)
Beispiel #24
0
def temporary_view(
    view_type: enums.TemporaryViewType = enums.TemporaryViewType.
    GalleryAddition,
    view_id: int = None,
    limit: int = 100,
    offset: int = 0,
    # sort_by: enums.ItemSort = None,
    # sort_desc: bool=False,
):
    """
    not ready yet...

    Args:
        view_type: type of temporary view
        view_id: id of a specific view
        limit: amount of items per page
        offset: offset the results by n items

    Returns:
        .. code-block:: guess

            {
                'items': [
                        ...
                    ],
                'count': int # count of all items in view
            }
    """
    view_type = enums.TemporaryViewType.get(view_type)
    d = {'items': [], 'count': 0}
    msg_obj = None

    sess = constants.db_session()
    sess.autoflush = False

    if view_type == enums.TemporaryViewType.GalleryAddition:
        msg_obj = message.GalleryFS
        c = constants.store.galleryfs_addition.get({})
        if view_id:
            c = list(c.get(view_id, tuple()))
        else:
            c = list(itertools.chain(*c.values()))

    d['count'] = len(c)
    d['items'] = [
        msg_obj(x).json_friendly(False) if msg_obj else x
        for x in c[offset:offset + limit]
    ]

    return message.Identity('items', d)
Beispiel #25
0
def get_tags_count():
    """
    Get count of namespacetags in the database

    Returns:
        .. code-block:: guess

            {
                'count' : int
            }
    """

    s = constants.db_session()

    return message.Identity('count', {'count': s.query(db.NamespaceTags).count()})
Beispiel #26
0
def update_metatags(item_type: enums.ItemType = enums.ItemType.Gallery,
                    item_id: int = 0,
                    metatags: dict = {}):
    """
    Update metatags for an item

    Args:
        item_type: possible items are :py:attr:`.ItemType.Gallery`, :py:attr:`.ItemType.Page`,
            :py:attr:`.ItemType.Artist`, :py:attr:`.ItemType.Collection`
        item_id: id of item
        metatag: a dict of ``{ metatag_name : bool }``

    Returns:
        bool indicating whether metatags were updated
    """
    if not item_id:
        raise exceptions.APIError(utils.this_function(),
                                  "item_id must be a valid item id")

    item_type = enums.ItemType.get(item_type)

    _, db_item = item_type._msg_and_model(
        (enums.ItemType.Gallery, enums.ItemType.Collection,
         enums.ItemType.Page, enums.ItemType.Artist))

    t = database_cmd.GetModelItems().run(db_item, {item_id})
    if not t:
        raise exceptions.DatabaseItemNotFoundError(
            utils.this_function(),
            "{} with item id '{}' not found".format(item_type, item_id))
    t = t[0]
    mtags = {}
    anames = db.MetaTag.all_names()
    for m, v in metatags.items():
        if m not in anames:
            raise exceptions.APIError(utils.this_function(),
                                      f"Metatag name '{m}' does not exist")
        mtags[m] = v

    st = True
    if t:
        t.update("metatags", mtags)

        db.object_session(t).commit()
    else:
        st = False

    return message.Identity('status', st)
Beispiel #27
0
def get_image(item_type: enums.ItemType = enums.ItemType.Gallery,
              item_ids: list = [],
              size: enums.ImageSize = enums.ImageSize.Medium,
              url: bool = False,
              uri: bool = False):
    """
    Get image for item.
    Image content is base64 encoded.

    Args:
        item_type: possible items are :py:attr:`.ItemType.Gallery`, :py:attr:`.ItemType.Artist`,
            :py:attr:`.ItemType.Collection`, :py:attr:`.ItemType.Grouping`, :py:attr:`.ItemType.Page`
        item_ids: list of item ids
        size: size of image
        url: replace image content with http url to image file
        uri: turn raw base64 string into an URI

    Returns:
        .. code-block:: guess

            {
                item_id : command_id
            }

    .. seealso::

        :func:`.get_image_from_path`
    """

    item_type = enums.ItemType.get(item_type)
    size = enums.ImageSize.get(size)

    _, db_item = item_type._msg_and_model(
        (enums.ItemType.Gallery, enums.ItemType.Collection,
         enums.ItemType.Grouping, enums.ItemType.Page, enums.ItemType.Artist))

    content = {}

    command_dec = functools.partial(_get_image, {'url': url, 'uri': uri})

    for i in item_ids:
        c = database_cmd.GetModelImage()
        services.ImageService.generic.add_command(c, command_dec)
        content[i] = c.start(db_item, i, size)

    return message.Identity('image', content)
Beispiel #28
0
def get_version():
    """
    Get version of components: 'core', 'db' and 'torrent'

    Returns:
        .. code-block:: guess

            {
                'core' : [int, int, int],
                'db' : [int, int, int],
                'torrent' : [int, int, int],
            }
    """
    vs = dict(core=list(constants.version),
              db=list(constants.version_db),
              torrent=(0, 0, 0))
    return message.Identity("version", vs)
Beispiel #29
0
def update_application(download_url: str = None, restart: bool = True):
    """
    Update the application with a new release.
    If download_url is not provided, a check for a new release will occur

    Args:
        download_url: a url to the release file, can be path to file on the system
        restart: restart the application after installing the new update


    Returns:
        A ``bool`` indicating whether the install was successful or not

    |async command|
    """

    upd = meta_cmd.UpdateApplication(AsyncService.generic).run(
        download_url, restart)
    return message.Identity('update', upd)
Beispiel #30
0
def open_gallery(item_id: int = 0,
                 item_type: enums.ItemType = enums.ItemType.Gallery,
                 viewer_args: str = None):
    """
    Open a gallery or page in an external viewer

    Args:
        item_id: id of item
        item_type: possible items are :py:attr:`.ItemType.Gallery`, :py:attr:`.ItemType.Page`
        viewer_args: commandline arguments to supply the viewer, overriding the default viewer arguments specified in settings

    Returns:
        bool indicating if item was successfully opened
    """
    item_type = enums.ItemType.get(item_type)

    _, db_model = item_type._msg_and_model(
        (enums.ItemType.Gallery, enums.ItemType.Page))
    kwargs = {}
    if item_type == enums.ItemType.Page:
        p = database_cmd.GetModelItems().run(db_model, {item_id},
                                             columns=(db_model.gallery_id,
                                                      db_model.number))
    else:
        p = database_cmd.GetModelItems().run(db_model, {item_id})
    if not p:
        raise exceptions.DatabaseItemNotFoundError(
            utils.this_function(),
            "{} with item id '{}' not found".format(item_type, item_id))
    p = p[0]
    if item_type == enums.ItemType.Page:
        kwargs['gallery_or_id'] = p[0]
        kwargs['number'] = p[1]
    else:
        kwargs["gallery_or_id"] = p

    if viewer_args:
        kwargs['args'] = tuple(x.strip() for x in viewer_args.split())

    opened = gallery_cmd.OpenGallery().run(**kwargs)

    return message.Identity("status", opened)