Skip to content

Attachments

Matrix file attachments. Full e2ee support is implemented.

AttachmentType

Bases: Enum

Enumeration containing the different types of media.

Attributes:

Name Type Description
FILE 'AttachmentType'

A generic file.

AUDIO 'AttachmentType'

An audio file.

VIDEO 'AttachmentType'

A video file.

IMAGE 'AttachmentType'

An image file.

BaseAttachment

Bases: ABC

Base class for attachments

Note

If you pass a custom file_name, this is only actually used if you pass a io.BytesIO to file. If you pass a pathlib.Path or a string, the file name will be resolved from the path, overriding the file_name parameter.

Parameters:

Name Type Description Default
file Union[str, BytesIO, PathLike, Path]

The file path or BytesIO object to upload.

required
file_name Optional[str]

The name of the file. Must be specified if uploading a BytesIO object.

None
mime_type Optional[str]

The mime type of the file. If not specified, it will be detected.

None
size_bytes Optional[int]

The size of the file in bytes. If not specified, it will be detected.

None
attachment_type AttachmentType

The type of attachment. Defaults to AttachmentType.FILE.

FILE

Attributes:

Name Type Description
file Union[Path, BytesIO]

The file path or BytesIO object to upload. Resolved to a pathlib.Path object if a string is passed to __init__.

file_name str

The name of the file. If file was a string or Path, this will be the name of the file.

mime_type str

The mime type of the file.

size int

The size of the file in bytes.

type AttachmentType

The type of attachment.

url Optional[str]

The URL of the uploaded file. This is set after the file is uploaded.

keys Optional[dict[str, str]]

The encryption keys for the file. This is set after the file is uploaded.

size_bytes property

size_bytes: int

Returns the size of this attachment in bytes.

as_body

as_body(body: Optional[str] = None) -> dict

Generates the body for the attachment for sending. The attachment must've been uploaded first.

Parameters:

Name Type Description Default
body Optional[str]

The body to use (should be a textual description). Defaults to the file name.

None

Returns:

Type Description
dict

from_file async classmethod

from_file(
    file: Union[str, BytesIO, Path],
    file_name: Optional[str] = None,
) -> "BaseAttachment"

Creates an attachment from a file.

You should use this method instead of the constructor, as it will automatically detect all other values

Parameters:

Name Type Description Default
file Union[str, BytesIO, Path]

The file or BytesIO to attach

required
file_name Optional[str]

The name of the BytesIO file, if applicable

None

Returns:

Type Description
'BaseAttachment'

Loaded attachment.

from_mxc async classmethod

from_mxc(client: 'NioBot', url: str) -> 'BaseAttachment'

Creates an attachment from an MXC URL.

Parameters:

Name Type Description Default
client 'NioBot'

The current client instance (used to download the attachment)

required
url str

The MXC:// url to download

required

Returns:

Type Description
'BaseAttachment'

The downloaded and probed attachment.

from_http async classmethod

from_http(
    url: str, client_session: Optional[ClientSession] = None
) -> "BaseAttachment"

Creates an attachment from an HTTP URL.

This is not necessarily just for images, video, or other media - it can be used for any HTTP resource.

Parameters:

Name Type Description Default
url str

The http/s URL to download

required
client_session Optional[ClientSession]

The aiohttp client session to use. If not specified, a new one will be created.

None

Returns:

Type Description
'BaseAttachment'

The downloaded and probed attachment.

Raises:

Type Description
niobot.MediaDownloadException

if the download failed.

aiohttp.ClientError

if the download failed.

niobot.MediaDetectionException

if the MIME type could not be detected.

size_as

size_as(
    unit: Literal[
        "b", "kb", "kib", "mb", "mib", "gb", "gib"
    ]
) -> Union[int, float]

Helper function to convert the size of this attachment into a different unit.

Remember: - 1 kilobyte (KB) is 1000 bytes - 1 kibibyte (KiB) is 1024 bytes

Example

>>> import niobot
>>> attachment = niobot.FileAttachment("background.png", "image/png")
>>> attachment.size_bytes
329945
>>> attachment.size_as("kb")
329.945
>>> attachment.size_as("kib")
322.2119140625
>>> attachment.size_as("mb")
0.329945
>>> attachment.size_as("mib")
0.31466007232666016
Note that due to the nature of floats, precision may be lost, especially the larger in units you go.

Parameters:

Name Type Description Default
unit Literal['b', 'kb', 'kib', 'mb', 'mib', 'gb', 'gib']

The unit to convert into

required

Returns:

Type Description
Union[int, float]

The converted size

upload async

upload(
    client: "NioBot", encrypted: bool = False
) -> "BaseAttachment"

Uploads the file to matrix.

Parameters:

Name Type Description Default
client 'NioBot'

The client to upload

required
encrypted bool

Whether to encrypt the attachment or not

False

Returns:

Type Description
'BaseAttachment'

The attachment

FileAttachment

Bases: BaseAttachment

Represents a generic file attachment.

You should use VideoAttachment for videos, AudioAttachment for audio, and ImageAttachment for images. This is for everything else.

Parameters:

Name Type Description Default
file Union[str, BytesIO, Path]

The file to upload

required
file_name Optional[str]

The name of the file

None
mime_type Optional[str]

The mime type of the file

None
size_bytes Optional[int]

The size of the file in bytes

None

ImageAttachment

Bases: BaseAttachment

Represents an image attachment.

Parameters:

Name Type Description Default
file Union[str, BytesIO, Path]

The file to upload

required
file_name Optional[str]

The name of the file

None
mime_type Optional[str]

The mime type of the file

None
size_bytes Optional[int]

The size of the file in bytes

None
height Optional[int]

The height of the image in pixels (e.g. 1080)

None
width Optional[int]

The width of the image in pixels (e.g. 1920)

None
thumbnail Optional['ImageAttachment']

A thumbnail of the image. NOT a blurhash.

None
xyz_amorgan_blurhash Optional[str]

The blurhash of the image

None

Attributes:

Name Type Description
info Dict

A dict of info about the image. Contains h, w, mimetype, and size keys.

thumbnail

A thumbnail of the image. NOT a blurhash.

info property

info: Dict

returns the info dictionary for this image.

Use ImageAttachment.as_body()["info"] instead.

from_file async classmethod

from_file(
    file: Union[str, BytesIO, Path],
    file_name: Optional[str] = None,
    height: Optional[int] = None,
    width: Optional[int] = None,
    thumbnail: Optional["ImageAttachment"] = None,
    generate_blurhash: bool = True,
    *,
    xyz_amorgan_blurhash: Optional[str] = None,
    unsafe: bool = False
) -> "ImageAttachment"

Generates an image attachment

Parameters:

Name Type Description Default
file Union[str, BytesIO, Path]

The file to upload

required
file_name Optional[str]

The name of the file (only used if file is a BytesIO)

None
height Optional[int]

The height, in pixels, of this image

None
width Optional[int]

The width, in pixels, of this image

None
thumbnail Optional['ImageAttachment']

A thumbnail for this image

None
generate_blurhash bool

Whether to generate a blurhash for this image

True
xyz_amorgan_blurhash Optional[str]

The blurhash of the image, if known beforehand.

None
unsafe bool

Whether to allow uploading of images with unsupported codecs. May break metadata detection.

False

Returns:

Type Description
'ImageAttachment'

An image attachment

thumbnailify_image staticmethod

thumbnailify_image(
    image: Union[Image, BytesIO, str, Path],
    size: Tuple[int, int] = (320, 240),
    resampling: Union["PIL.Image.Resampling"] = BICUBIC,
) -> Image

Helper function to thumbnail an image.

This function is blocking - you should use niobot.utils.run_blocking to run it.

Parameters:

Name Type Description Default
image Union[Image, BytesIO, str, Path]

The image to thumbnail

required
size Tuple[int, int]

The size to thumbnail to. Defaults to 320x240, a standard thumbnail size.

(320, 240)
resampling Union['PIL.Image.Resampling']

The resampling filter to use. Defaults to PIL.Image.BICUBIC, a high-quality but fast resampling method. For the highest quality, use PIL.Image.LANCZOS.

BICUBIC

Returns:

Type Description
Image

The thumbnail

get_blurhash async

get_blurhash(
    quality: Tuple[int, int] = (4, 3),
    file: Optional[Union[str, Path, BytesIO, Image]] = None,
    disable_auto_crop: bool = False,
) -> str

Gets the blurhash of the attachment. See: woltapp/blurhash

You should crop-down your blurhash images.

Generating blurhashes can take a long time, especially on large images. You should crop-down your images to a reasonable size before generating the blurhash.

Remember, most image quality is lost - there's very little point in generating a blurhash for a 4K image. Anything over 800x600 is definitely overkill.

You can easily resize images with niobot.ImageAttachment.thumbnailify_image:

attachment = await niobot.ImageAttachment.from_file(my_image, generate_blurhash=False)
await attachment.get_blurhash(file=attachment.thumbnailify_image(attachment.file))

This will generate a roughly 320x240 thumbnail image, and generate the blurhash from that.

New!

Unless you pass disable_auto_crop=True, this function will automatically crop the image down to a reasonable size, before generating a blurhash.

Parameters:

Name Type Description Default
quality Tuple[int, int]

A tuple of the quality to generate the blurhash at. Defaults to (4, 3).

(4, 3)
file Optional[Union[str, Path, BytesIO, Image]]

The file to generate the blurhash from. Defaults to the file passed in the constructor.

None
disable_auto_crop bool

Whether to disable automatic cropping of the image. Defaults to False.

False

Returns:

Type Description
str

The blurhash

VideoAttachment

Bases: BaseAttachment

Represents a video attachment.

Parameters:

Name Type Description Default
file Union[str, BytesIO, Path]

The file to upload

required
file_name Optional[str]

The name of the file

None
mime_type Optional[str]

The mime type of the file

None
size_bytes Optional[int]

The size of the file in bytes

None
height Optional[int]

The height of the video in pixels (e.g. 1080)

None
width Optional[int]

The width of the video in pixels (e.g. 1920)

None
duration Optional[int]

The duration of the video in seconds

None
thumbnail Optional['ImageAttachment']

A thumbnail of the video. NOT a blurhash.

None

from_file async classmethod

from_file(
    file: Union[str, BytesIO, Path],
    file_name: Optional[str] = None,
    duration: Optional[int] = None,
    height: Optional[int] = None,
    width: Optional[int] = None,
    thumbnail: Optional[
        Union[ImageAttachment, Literal[False]]
    ] = None,
    generate_blurhash: bool = True,
) -> "VideoAttachment"

Generates a video attachment

This function auto-generates a thumbnail!

As thumbnails greatly improve user experience, even with blurhashes enabled, this function will by default create a thumbnail of the first frame of the given video if you do not provide one yourself. This may increase your initialisation time by a couple seconds, give or take!

If this is undesirable, pass thumbnail=False to disable generating a thumbnail. This is independent of generate_blurhash.

Generated thumbnails are always WebP images, so they will always be miniature, so you shouldn't notice a significant increase in upload time, especially considering your video will likely be several megabytes.

Parameters:

Name Type Description Default
file Union[str, BytesIO, Path]

The file to upload

required
file_name Optional[str]

The name of the file (only used if file is a BytesIO)

None
duration Optional[int]

The duration of the video, in seconds

None
height Optional[int]

The height, in pixels, of this video

None
width Optional[int]

The width, in pixels, of this video

None
thumbnail Optional[Union[ImageAttachment, Literal[False]]]

A thumbnail for this image

None
generate_blurhash bool

Whether to generate a blurhash for this image

True

Returns:

Type Description
'VideoAttachment'

An image attachment

generate_thumbnail async staticmethod

generate_thumbnail(
    video: Union[str, Path, "VideoAttachment"]
) -> ImageAttachment

Generates a thumbnail for a video.

Parameters:

Name Type Description Default
video Union[str, Path, 'VideoAttachment']

The video to generate a thumbnail for

required

Returns:

Type Description
ImageAttachment

The path to the generated thumbnail

AudioAttachment

Bases: BaseAttachment

Represents an audio attachment.

duration property writable

duration: Optional[int]

The duration of this audio in milliseconds

from_file async classmethod

from_file(
    file: Union[str, BytesIO, Path],
    file_name: Optional[str] = None,
    duration: Optional[int] = None,
) -> "AudioAttachment"

Generates an audio attachment

Parameters:

Name Type Description Default
file Union[str, BytesIO, Path]

The file to upload

required
file_name Optional[str]

The name of the file (only used if file is a BytesIO)

None
duration Optional[int]

The duration of the audio, in seconds

None

Returns:

Type Description
'AudioAttachment'

An audio attachment

detect_mime_type

detect_mime_type(file: Union[str, BytesIO, Path]) -> str

Detect the mime type of a file.

Parameters:

Name Type Description Default
file Union[str, BytesIO, Path]

The file to detect the mime type of. Can be a BytesIO.

required

Returns:

Type Description
str

The mime type of the file (e.g. text/plain, image/png, application/pdf, video/webp etc.)

Raises:

Type Description
RuntimeError

If the magic library is not installed.

TypeError

If the file is not a string, BytesIO, or Path object.

get_metadata_ffmpeg

get_metadata_ffmpeg(
    file: Union[str, Path]
) -> dict[str, Any]

Gets metadata for a file via ffprobe.

example output (JSON)

Parameters:

Name Type Description Default
file Union[str, Path]

The file to get metadata for. Must be a path-like object

required

Returns:

Type Description
dict[str, Any]

A dictionary containing the metadata.

get_metadata_imagemagick

get_metadata_imagemagick(file: Path) -> dict[str, Any]

The same as get_metadata_ffmpeg but for ImageMagick.

Only returns a limited subset of the data, such as one stream, which contains the format, and size, and the format, which contains the filename, format, and size.

example output (JSON)

Parameters:

Name Type Description Default
file Path

The file to get metadata for. Must be a path object

required

Returns:

Type Description
dict[str, Any]

A slimmed-down dictionary containing the metadata.

get_metadata

get_metadata(
    file: Union[str, Path], mime_type: Optional[str] = None
) -> dict[str, Any]

Gets metadata for a file.

This will use imagemagick (identify) for images where available, falling back to ffmpeg (ffprobe) for everything else.

Parameters:

Name Type Description Default
file Union[str, Path]

The file to get metadata for.

required
mime_type Optional[str]

The mime type of the file. If not provided, it will be detected.

None

Returns:

Type Description
dict[str, Any]

The metadata for the file. See niobot.get_metadata_ffmpeg and niobot.get_metadata_imagemagick for more information.

first_frame

first_frame(
    file: Union[str, Path], file_format: str = "webp"
) -> bytes

Gets the first frame of a video file.

This function creates a file on disk

In order to extract the frame, this function creates a temporary file on disk (or memdisk depending on where your tempdir is). While this file is deleted after the function is done, it is still something to be aware of. For example, if you're (worryingly) low on space, this function may fail to extract the frame due to a lack of space. Or, someone could temporarily access and read the file before it is deleted.

This also means that this function may be slow.

Parameters:

Name Type Description Default
file Union[str, Path]

The file to get the first frame of. Must be a path-like object

required
file_format str

The format to save the frame as. Defaults to webp.

'webp'

Returns:

Type Description
bytes

The first frame of the video in bytes.

generate_blur_hash

generate_blur_hash(
    file: Union[str, Path, BytesIO, Image], *parts: int
) -> str

Creates a blurhash

This function may be resource intensive

This function may be resource intensive, especially for large images. You should run this in a thread or process pool.

You should also scale any images down in order to increase performance.

See: woltapp/blurhash

which

which(
    file: Union[BytesIO, Path, str],
    mime_type: Optional[str] = None,
) -> Union[
    Type["FileAttachment"],
    Type["ImageAttachment"],
    Type["AudioAttachment"],
    Type["VideoAttachment"],
]

Gets the correct attachment type for a file.

This function will provide either Image/Video/Audio attachment where possible, or FileAttachment otherwise.

For example, image/png (from my_image.png) will see image/ and will return ImageAttachment, and video/mp4 (from my_video.mp4) will see video/ and will return VideoAttachment.

If the mime type cannot be mapped to an attachment type, this function will return FileAttachment.

Usage
import niobot
import pathlib

my_file = pathlib.Path("/tmp/foo.bar")
attachment = await niobot.which(my_file).from_file(my_file)
# or
attachment_type = niobot.which(my_file)  # one of the BaseAttachment subclasses
attachment = await attachment_type.from_file(my_file)

Parameters:

Name Type Description Default
file Union[BytesIO, Path, str]

The file or BytesIO to investigate

required
mime_type Optional[str]

The optional pre-detected mime type. If this is not provided, it will be detected.

None

Returns:

Type Description
Union[Type['FileAttachment'], Type['ImageAttachment'], Type['AudioAttachment'], Type['VideoAttachment']]

The correct type for this attachment (not instantiated)