Add strict typing of account & instance to Mastodon (#139739)

Add strict typing of account & instance
This commit is contained in:
Andrew Jackson 2025-03-10 14:54:18 +00:00 committed by GitHub
parent ed20947e30
commit 290116029b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 146 additions and 457 deletions

View File

@ -2,7 +2,7 @@
from __future__ import annotations
from mastodon.Mastodon import Mastodon, MastodonError
from mastodon.Mastodon import Account, Instance, InstanceV2, Mastodon, MastodonError
from homeassistant.const import (
CONF_ACCESS_TOKEN,
@ -107,7 +107,9 @@ async def async_migrate_entry(hass: HomeAssistant, entry: MastodonConfigEntry) -
return True
def setup_mastodon(entry: MastodonConfigEntry) -> tuple[Mastodon, dict, dict]:
def setup_mastodon(
entry: MastodonConfigEntry,
) -> tuple[Mastodon, InstanceV2 | Instance, Account]:
"""Get mastodon details."""
client = create_mastodon_client(
entry.data[CONF_BASE_URL],

View File

@ -4,7 +4,12 @@ from __future__ import annotations
from typing import Any
from mastodon.Mastodon import MastodonNetworkError, MastodonUnauthorizedError
from mastodon.Mastodon import (
Account,
Instance,
MastodonNetworkError,
MastodonUnauthorizedError,
)
import voluptuous as vol
from yarl import URL
@ -56,8 +61,8 @@ class MastodonConfigFlow(ConfigFlow, domain=DOMAIN):
client_secret: str,
access_token: str,
) -> tuple[
dict[str, str] | None,
dict[str, str] | None,
Instance | None,
Account | None,
dict[str, str],
]:
"""Check connection to the Mastodon instance."""

View File

@ -12,14 +12,6 @@ DATA_HASS_CONFIG = "mastodon_hass_config"
DEFAULT_URL: Final = "https://mastodon.social"
DEFAULT_NAME: Final = "Mastodon"
INSTANCE_VERSION: Final = "version"
INSTANCE_URI: Final = "uri"
INSTANCE_DOMAIN: Final = "domain"
ACCOUNT_USERNAME: Final = "username"
ACCOUNT_FOLLOWERS_COUNT: Final = "followers_count"
ACCOUNT_FOLLOWING_COUNT: Final = "following_count"
ACCOUNT_STATUSES_COUNT: Final = "statuses_count"
ATTR_CONFIG_ENTRY_ID = "config_entry_id"
ATTR_STATUS = "status"
ATTR_VISIBILITY = "visibility"

View File

@ -4,10 +4,9 @@ from __future__ import annotations
from dataclasses import dataclass
from datetime import timedelta
from typing import Any
from mastodon import Mastodon
from mastodon.Mastodon import MastodonError
from mastodon.Mastodon import Account, Instance, InstanceV2, MastodonError
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
@ -21,15 +20,15 @@ class MastodonData:
"""Mastodon data type."""
client: Mastodon
instance: dict
account: dict
instance: InstanceV2 | Instance
account: Account
coordinator: MastodonCoordinator
type MastodonConfigEntry = ConfigEntry[MastodonData]
class MastodonCoordinator(DataUpdateCoordinator[dict[str, Any]]):
class MastodonCoordinator(DataUpdateCoordinator[Account]):
"""Class to manage fetching Mastodon data."""
config_entry: MastodonConfigEntry
@ -47,9 +46,9 @@ class MastodonCoordinator(DataUpdateCoordinator[dict[str, Any]]):
)
self.client = client
async def _async_update_data(self) -> dict[str, Any]:
async def _async_update_data(self) -> Account:
try:
account: dict = await self.hass.async_add_executor_job(
account: Account = await self.hass.async_add_executor_job(
self.client.account_verify_credentials
)
except MastodonError as ex:

View File

@ -4,6 +4,8 @@ from __future__ import annotations
from typing import Any
from mastodon.Mastodon import Account, Instance
from homeassistant.core import HomeAssistant
from .coordinator import MastodonConfigEntry
@ -25,7 +27,7 @@ async def async_get_config_entry_diagnostics(
}
def get_diagnostics(config_entry: MastodonConfigEntry) -> tuple[dict, dict]:
def get_diagnostics(config_entry: MastodonConfigEntry) -> tuple[Instance, Account]:
"""Get mastodon diagnostics."""
client = config_entry.runtime_data.client

View File

@ -4,7 +4,7 @@ from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
from homeassistant.helpers.entity import EntityDescription
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import DEFAULT_NAME, DOMAIN, INSTANCE_VERSION
from .const import DEFAULT_NAME, DOMAIN
from .coordinator import MastodonConfigEntry, MastodonCoordinator
from .utils import construct_mastodon_username
@ -40,7 +40,7 @@ class MastodonEntity(CoordinatorEntity[MastodonCoordinator]):
manufacturer="Mastodon gGmbH",
model=full_account_name,
entry_type=DeviceEntryType.SERVICE,
sw_version=data.runtime_data.instance[INSTANCE_VERSION],
sw_version=data.runtime_data.instance.version,
name=name,
)

View File

@ -4,7 +4,8 @@ from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
from typing import Any
from mastodon.Mastodon import Account
from homeassistant.components.sensor import (
SensorEntity,
@ -15,11 +16,6 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.typing import StateType
from .const import (
ACCOUNT_FOLLOWERS_COUNT,
ACCOUNT_FOLLOWING_COUNT,
ACCOUNT_STATUSES_COUNT,
)
from .coordinator import MastodonConfigEntry
from .entity import MastodonEntity
@ -31,7 +27,7 @@ PARALLEL_UPDATES = 0
class MastodonSensorEntityDescription(SensorEntityDescription):
"""Describes Mastodon sensor entity."""
value_fn: Callable[[dict[str, Any]], StateType]
value_fn: Callable[[Account], StateType]
ENTITY_DESCRIPTIONS = (
@ -39,19 +35,19 @@ ENTITY_DESCRIPTIONS = (
key="followers",
translation_key="followers",
state_class=SensorStateClass.TOTAL,
value_fn=lambda data: data.get(ACCOUNT_FOLLOWERS_COUNT),
value_fn=lambda data: data.followers_count,
),
MastodonSensorEntityDescription(
key="following",
translation_key="following",
state_class=SensorStateClass.TOTAL,
value_fn=lambda data: data.get(ACCOUNT_FOLLOWING_COUNT),
value_fn=lambda data: data.following_count,
),
MastodonSensorEntityDescription(
key="posts",
translation_key="posts",
state_class=SensorStateClass.TOTAL,
value_fn=lambda data: data.get(ACCOUNT_STATUSES_COUNT),
value_fn=lambda data: data.statuses_count,
),
)

View File

@ -6,8 +6,9 @@ import mimetypes
from typing import Any
from mastodon import Mastodon
from mastodon.Mastodon import Account, Instance, InstanceV2
from .const import ACCOUNT_USERNAME, DEFAULT_NAME, INSTANCE_DOMAIN, INSTANCE_URI
from .const import DEFAULT_NAME
def create_mastodon_client(
@ -23,14 +24,13 @@ def create_mastodon_client(
def construct_mastodon_username(
instance: dict[str, str] | None, account: dict[str, str] | None
instance: InstanceV2 | Instance | None, account: Account | None
) -> str:
"""Construct a mastodon username from the account and instance."""
if instance and account:
return (
f"@{account[ACCOUNT_USERNAME]}@"
f"{instance.get(INSTANCE_URI, instance.get(INSTANCE_DOMAIN))}"
)
if type(instance) is InstanceV2:
return f"@{account.username}@{instance.domain}"
return f"@{account.username}@{instance.uri}"
return DEFAULT_NAME

View File

@ -3,12 +3,13 @@
from collections.abc import Generator
from unittest.mock import AsyncMock, patch
from mastodon.Mastodon import Account, InstanceV2
import pytest
from homeassistant.components.mastodon.const import CONF_BASE_URL, DOMAIN
from homeassistant.const import CONF_ACCESS_TOKEN, CONF_CLIENT_ID, CONF_CLIENT_SECRET
from tests.common import MockConfigEntry, load_json_object_fixture
from tests.common import MockConfigEntry, load_fixture
@pytest.fixture
@ -31,9 +32,11 @@ def mock_mastodon_client() -> Generator[AsyncMock]:
) as mock_client,
):
client = mock_client.return_value
client.instance.return_value = load_json_object_fixture("instance.json", DOMAIN)
client.account_verify_credentials.return_value = load_json_object_fixture(
"account_verify_credentials.json", DOMAIN
client.instance.return_value = InstanceV2.from_json(
load_fixture("instance.json", DOMAIN)
)
client.account_verify_credentials.return_value = Account.from_json(
load_fixture("account_verify_credentials.json", DOMAIN)
)
client.status_post.return_value = None
yield client

View File

@ -1,78 +1,60 @@
{
"id": "14715",
"username": "trwnh",
"acct": "trwnh",
"display_name": "infinite love ⴳ",
"locked": false,
"bot": false,
"created_at": "2016-11-24T10:02:12.085Z",
"note": "<p>i have approximate knowledge of many things. perpetual student. (nb/ace/they)</p><p>xmpp/email: a@trwnh.com<br /><a href=\"https://trwnh.com\" rel=\"nofollow noopener noreferrer\" target=\"_blank\"><span class=\"invisible\">https://</span><span class=\"\">trwnh.com</span><span class=\"invisible\"></span></a><br />help me live: <a href=\"https://liberapay.com/at\" rel=\"nofollow noopener noreferrer\" target=\"_blank\"><span class=\"invisible\">https://</span><span class=\"\">liberapay.com/at</span><span class=\"invisible\"></span></a> or <a href=\"https://paypal.me/trwnh\" rel=\"nofollow noopener noreferrer\" target=\"_blank\"><span class=\"invisible\">https://</span><span class=\"\">paypal.me/trwnh</span><span class=\"invisible\"></span></a></p><p>- my triggers are moths and glitter<br />- i have all notifs except mentions turned off, so please interact if you wanna be friends! i literally will not notice otherwise<br />- dm me if i did something wrong, so i can improve<br />- purest person on fedi, do not lewd in my presence<br />- #1 ami cole fan account</p><p>:fatyoshi:</p>",
"url": "https://mastodon.social/@trwnh",
"avatar": "https://files.mastodon.social/accounts/avatars/000/014/715/original/34aa222f4ae2e0a9.png",
"avatar_static": "https://files.mastodon.social/accounts/avatars/000/014/715/original/34aa222f4ae2e0a9.png",
"header": "https://files.mastodon.social/accounts/headers/000/014/715/original/5c6fc24edb3bb873.jpg",
"header_static": "https://files.mastodon.social/accounts/headers/000/014/715/original/5c6fc24edb3bb873.jpg",
"followers_count": 821,
"following_count": 178,
"statuses_count": 33120,
"last_status_at": "2019-11-24T15:49:42.251Z",
"source": {
"privacy": "public",
"sensitive": false,
"language": "",
"note": "i have approximate knowledge of many things. perpetual student. (nb/ace/they)\r\n\r\nxmpp/email: a@trwnh.com\r\nhttps://trwnh.com\r\nhelp me live: https://liberapay.com/at or https://paypal.me/trwnh\r\n\r\n- my triggers are moths and glitter\r\n- i have all notifs except mentions turned off, so please interact if you wanna be friends! i literally will not notice otherwise\r\n- dm me if i did something wrong, so i can improve\r\n- purest person on fedi, do not lewd in my presence\r\n- #1 ami cole fan account\r\n\r\n:fatyoshi:",
"_mastopy_version": "2.0.0",
"_mastopy_type": "Account",
"_mastopy_data": {
"id": "14715",
"username": "trwnh",
"acct": "trwnh",
"display_name": "infinite love \u2d33",
"discoverable": true,
"group": false,
"locked": false,
"created_at": "2016-11-24T00:00:00+00:00",
"following_count": 328,
"followers_count": 3169,
"statuses_count": 69523,
"note": "<p>i have approximate knowledge of many things. perpetual student. (nb/ace/they)</p><p>xmpp/email: a@trwnh.com<br /><a href=\"https://trwnh.com\" target=\"_blank\" rel=\"nofollow noopener\" translate=\"no\"><span class=\"invisible\">https://</span><span class=\"\">trwnh.com</span><span class=\"invisible\"></span></a><br />help me live:<br />- <a href=\"https://donate.stripe.com/4gwcPCaMpcQ19RC4gg\" target=\"_blank\" rel=\"nofollow noopener\" translate=\"no\"><span class=\"invisible\">https://</span><span class=\"ellipsis\">donate.stripe.com/4gwcPCaMpcQ1</span><span class=\"invisible\">9RC4gg</span></a><br />- <a href=\"https://liberapay.com/trwnh\" target=\"_blank\" rel=\"nofollow noopener\" translate=\"no\"><span class=\"invisible\">https://</span><span class=\"\">liberapay.com/trwnh</span><span class=\"invisible\"></span></a></p><p>notes:<br />- my triggers are moths and glitter<br />- i have all notifs except mentions turned off, so please interact if you wanna be friends! i literally will not notice otherwise<br />- dm me if i did something wrong, so i can improve<br />- purest person on fedi, do not lewd in my presence</p>",
"url": "https://mastodon.social/@trwnh",
"uri": "https://mastodon.social/users/trwnh",
"avatar": "https://files.mastodon.social/accounts/avatars/000/014/715/original/051c958388818705.png",
"header": "https://files.mastodon.social/accounts/headers/000/014/715/original/5c6fc24edb3bb873.jpg",
"avatar_static": "https://files.mastodon.social/accounts/avatars/000/014/715/original/051c958388818705.png",
"header_static": "https://files.mastodon.social/accounts/headers/000/014/715/original/5c6fc24edb3bb873.jpg",
"moved_to_account": null,
"suspended": null,
"limited": null,
"bot": true,
"fields": [
{
"name": "Website",
"value": "https://trwnh.com",
"value": "<a href=\"https://trwnh.com\" target=\"_blank\" rel=\"nofollow noopener me\" translate=\"no\"><span class=\"invisible\">https://</span><span class=\"\">trwnh.com</span><span class=\"invisible\"></span></a>",
"verified_at": "2019-08-29T04:14:55.571+00:00"
},
{
"name": "Sponsor",
"value": "https://liberapay.com/at",
"verified_at": "2019-11-15T10:06:15.557+00:00"
"name": "Portfolio",
"value": "<a href=\"https://abdullahtarawneh.com\" target=\"_blank\" rel=\"nofollow noopener me\" translate=\"no\"><span class=\"invisible\">https://</span><span class=\"\">abdullahtarawneh.com</span><span class=\"invisible\"></span></a>",
"verified_at": "2021-02-11T20:34:13.574+00:00"
},
{
"name": "Fan of:",
"value": "Punk-rock and post-hardcore (Circa Survive, letlive., La Dispute, THE FEVER 333)Manga (Yu-Gi-Oh!, One Piece, JoJo's Bizarre Adventure, Death Note, Shaman King)Platformers and RPGs (Banjo-Kazooie, Boktai, Final Fantasy Crystal Chronicles)",
"value": "Punk-rock and post-hardcore (Circa Survive, letlive., La Dispute, THE FEVER 333)Manga (Yu-Gi-Oh!, One Piece, JoJo&#39;s Bizarre Adventure, Death Note, Shaman King)Platformers and RPGs (Banjo-Kazooie, Boktai, Final Fantasy Crystal Chronicles)",
"verified_at": null
},
{
"name": "Main topics:",
"value": "systemic analysis, design patterns, anticapitalism, info/tech freedom, theory and philosophy, and otherwise being a genuine and decent wholesome poster. i'm just here to hang out and talk to cool people!",
"name": "What to expect:",
"value": "talking about various things i find interesting, and otherwise being a genuine and decent wholesome poster. i&#39;m just here to hang out and talk to cool people! and to spill my thoughts.",
"verified_at": null
}
],
"follow_requests_count": 0
},
"emojis": [
{
"shortcode": "fatyoshi",
"url": "https://files.mastodon.social/custom_emojis/images/000/023/920/original/e57ecb623faa0dc9.png",
"static_url": "https://files.mastodon.social/custom_emojis/images/000/023/920/static/e57ecb623faa0dc9.png",
"visible_in_picker": true
}
],
"fields": [
{
"name": "Website",
"value": "<a href=\"https://trwnh.com\" rel=\"me nofollow noopener noreferrer\" target=\"_blank\"><span class=\"invisible\">https://</span><span class=\"\">trwnh.com</span><span class=\"invisible\"></span></a>",
"verified_at": "2019-08-29T04:14:55.571+00:00"
},
{
"name": "Sponsor",
"value": "<a href=\"https://liberapay.com/at\" rel=\"me nofollow noopener noreferrer\" target=\"_blank\"><span class=\"invisible\">https://</span><span class=\"\">liberapay.com/at</span><span class=\"invisible\"></span></a>",
"verified_at": "2019-11-15T10:06:15.557+00:00"
},
{
"name": "Fan of:",
"value": "Punk-rock and post-hardcore (Circa Survive, letlive., La Dispute, THE FEVER 333)Manga (Yu-Gi-Oh!, One Piece, JoJo&apos;s Bizarre Adventure, Death Note, Shaman King)Platformers and RPGs (Banjo-Kazooie, Boktai, Final Fantasy Crystal Chronicles)",
"verified_at": null
},
{
"name": "Main topics:",
"value": "systemic analysis, design patterns, anticapitalism, info/tech freedom, theory and philosophy, and otherwise being a genuine and decent wholesome poster. i&apos;m just here to hang out and talk to cool people!",
"verified_at": null
}
]
"emojis": [],
"last_status_at": "2025-03-04T00:00:00",
"noindex": false,
"roles": [],
"role": null,
"source": null,
"mute_expires_at": null,
"indexable": false,
"hide_collections": true,
"memorial": null
}
}

View File

@ -1,147 +1,18 @@
{
"domain": "mastodon.social",
"title": "Mastodon",
"version": "4.0.0rc1",
"source_url": "https://github.com/mastodon/mastodon",
"description": "The original server operated by the Mastodon gGmbH non-profit",
"usage": {
"users": {
"active_month": 123122
"_mastopy_version": "2.0.0",
"_mastopy_type": "InstanceV2",
"_mastopy_data": {
"uri": "mastodon.social",
"domain": "mastodon.social",
"title": "Mastodon",
"version": "4.4.0-nightly.2025-02-07",
"source_url": "https://github.com/mastodon/mastodon",
"description": "The original server operated by the Mastodon gGmbH non-profit",
"usage": {
"users": {
"active_month": 380143
}
}
},
"thumbnail": {
"url": "https://files.mastodon.social/site_uploads/files/000/000/001/@1x/57c12f441d083cde.png",
"blurhash": "UeKUpFxuo~R%0nW;WCnhF6RjaJt757oJodS$",
"versions": {
"@1x": "https://files.mastodon.social/site_uploads/files/000/000/001/@1x/57c12f441d083cde.png",
"@2x": "https://files.mastodon.social/site_uploads/files/000/000/001/@2x/57c12f441d083cde.png"
}
},
"languages": ["en"],
"configuration": {
"urls": {
"streaming": "wss://mastodon.social"
},
"vapid": {
"public_key": "BCkMmVdKDnKYwzVCDC99Iuc9GvId-x7-kKtuHnLgfF98ENiZp_aj-UNthbCdI70DqN1zUVis-x0Wrot2sBagkMc="
},
"accounts": {
"max_featured_tags": 10,
"max_pinned_statuses": 4
},
"statuses": {
"max_characters": 500,
"max_media_attachments": 4,
"characters_reserved_per_url": 23
},
"media_attachments": {
"supported_mime_types": [
"image/jpeg",
"image/png",
"image/gif",
"image/heic",
"image/heif",
"image/webp",
"video/webm",
"video/mp4",
"video/quicktime",
"video/ogg",
"audio/wave",
"audio/wav",
"audio/x-wav",
"audio/x-pn-wave",
"audio/vnd.wave",
"audio/ogg",
"audio/vorbis",
"audio/mpeg",
"audio/mp3",
"audio/webm",
"audio/flac",
"audio/aac",
"audio/m4a",
"audio/x-m4a",
"audio/mp4",
"audio/3gpp",
"video/x-ms-asf"
],
"image_size_limit": 10485760,
"image_matrix_limit": 16777216,
"video_size_limit": 41943040,
"video_frame_rate_limit": 60,
"video_matrix_limit": 2304000
},
"polls": {
"max_options": 4,
"max_characters_per_option": 50,
"min_expiration": 300,
"max_expiration": 2629746
},
"translation": {
"enabled": true
}
},
"registrations": {
"enabled": false,
"approval_required": false,
"message": null
},
"contact": {
"email": "staff@mastodon.social",
"account": {
"id": "1",
"username": "Gargron",
"acct": "Gargron",
"display_name": "Eugen 💀",
"locked": false,
"bot": false,
"discoverable": true,
"group": false,
"created_at": "2016-03-16T00:00:00.000Z",
"note": "<p>Founder, CEO and lead developer <span class=\"h-card\"><a href=\"https://mastodon.social/@Mastodon\" class=\"u-url mention\">@<span>Mastodon</span></a></span>, Germany.</p>",
"url": "https://mastodon.social/@Gargron",
"avatar": "https://files.mastodon.social/accounts/avatars/000/000/001/original/dc4286ceb8fab734.jpg",
"avatar_static": "https://files.mastodon.social/accounts/avatars/000/000/001/original/dc4286ceb8fab734.jpg",
"header": "https://files.mastodon.social/accounts/headers/000/000/001/original/3b91c9965d00888b.jpeg",
"header_static": "https://files.mastodon.social/accounts/headers/000/000/001/original/3b91c9965d00888b.jpeg",
"followers_count": 133026,
"following_count": 311,
"statuses_count": 72605,
"last_status_at": "2022-10-31",
"noindex": false,
"emojis": [],
"fields": [
{
"name": "Patreon",
"value": "<a href=\"https://www.patreon.com/mastodon\" target=\"_blank\" rel=\"nofollow noopener noreferrer me\"><span class=\"invisible\">https://www.</span><span class=\"\">patreon.com/mastodon</span><span class=\"invisible\"></span></a>",
"verified_at": null
}
]
}
},
"rules": [
{
"id": "1",
"text": "Sexually explicit or violent media must be marked as sensitive when posting"
},
{
"id": "2",
"text": "No racism, sexism, homophobia, transphobia, xenophobia, or casteism"
},
{
"id": "3",
"text": "No incitement of violence or promotion of violent ideologies"
},
{
"id": "4",
"text": "No harassment, dogpiling or doxxing of other users"
},
{
"id": "5",
"text": "No content illegal in Germany"
},
{
"id": "7",
"text": "Do not share intentionally false or misleading information"
}
]
}
}

View File

@ -3,245 +3,82 @@
dict({
'account': dict({
'acct': 'trwnh',
'avatar': 'https://files.mastodon.social/accounts/avatars/000/014/715/original/34aa222f4ae2e0a9.png',
'avatar_static': 'https://files.mastodon.social/accounts/avatars/000/014/715/original/34aa222f4ae2e0a9.png',
'bot': False,
'created_at': '2016-11-24T10:02:12.085Z',
'avatar': 'https://files.mastodon.social/accounts/avatars/000/014/715/original/051c958388818705.png',
'avatar_static': 'https://files.mastodon.social/accounts/avatars/000/014/715/original/051c958388818705.png',
'bot': True,
'created_at': '2016-11-24T00:00:00+00:00',
'discoverable': True,
'display_name': 'infinite love ⴳ',
'emojis': list([
dict({
'shortcode': 'fatyoshi',
'static_url': 'https://files.mastodon.social/custom_emojis/images/000/023/920/static/e57ecb623faa0dc9.png',
'url': 'https://files.mastodon.social/custom_emojis/images/000/023/920/original/e57ecb623faa0dc9.png',
'visible_in_picker': True,
}),
]),
'fields': list([
dict({
'name': 'Website',
'value': '<a href="https://trwnh.com" rel="me nofollow noopener noreferrer" target="_blank"><span class="invisible">https://</span><span class="">trwnh.com</span><span class="invisible"></span></a>',
'value': '<a href="https://trwnh.com" target="_blank" rel="nofollow noopener me" translate="no"><span class="invisible">https://</span><span class="">trwnh.com</span><span class="invisible"></span></a>',
'verified_at': '2019-08-29T04:14:55.571+00:00',
}),
dict({
'name': 'Sponsor',
'value': '<a href="https://liberapay.com/at" rel="me nofollow noopener noreferrer" target="_blank"><span class="invisible">https://</span><span class="">liberapay.com/at</span><span class="invisible"></span></a>',
'verified_at': '2019-11-15T10:06:15.557+00:00',
'name': 'Portfolio',
'value': '<a href="https://abdullahtarawneh.com" target="_blank" rel="nofollow noopener me" translate="no"><span class="invisible">https://</span><span class="">abdullahtarawneh.com</span><span class="invisible"></span></a>',
'verified_at': '2021-02-11T20:34:13.574+00:00',
}),
dict({
'name': 'Fan of:',
'value': 'Punk-rock and post-hardcore (Circa Survive, letlive., La Dispute, THE FEVER 333)Manga (Yu-Gi-Oh!, One Piece, JoJo&apos;s Bizarre Adventure, Death Note, Shaman King)Platformers and RPGs (Banjo-Kazooie, Boktai, Final Fantasy Crystal Chronicles)',
'value': 'Punk-rock and post-hardcore (Circa Survive, letlive., La Dispute, THE FEVER 333)Manga (Yu-Gi-Oh!, One Piece, JoJo&#39;s Bizarre Adventure, Death Note, Shaman King)Platformers and RPGs (Banjo-Kazooie, Boktai, Final Fantasy Crystal Chronicles)',
'verified_at': None,
}),
dict({
'name': 'Main topics:',
'value': 'systemic analysis, design patterns, anticapitalism, info/tech freedom, theory and philosophy, and otherwise being a genuine and decent wholesome poster. i&apos;m just here to hang out and talk to cool people!',
'name': 'What to expect:',
'value': 'talking about various things i find interesting, and otherwise being a genuine and decent wholesome poster. i&#39;m just here to hang out and talk to cool people! and to spill my thoughts.',
'verified_at': None,
}),
]),
'followers_count': 821,
'following_count': 178,
'followers_count': 3169,
'following_count': 328,
'group': False,
'header': 'https://files.mastodon.social/accounts/headers/000/014/715/original/5c6fc24edb3bb873.jpg',
'header_static': 'https://files.mastodon.social/accounts/headers/000/014/715/original/5c6fc24edb3bb873.jpg',
'hide_collections': True,
'id': '14715',
'last_status_at': '2019-11-24T15:49:42.251Z',
'indexable': False,
'last_status_at': '2025-03-04T00:00:00',
'limited': None,
'locked': False,
'note': '<p>i have approximate knowledge of many things. perpetual student. (nb/ace/they)</p><p>xmpp/email: a@trwnh.com<br /><a href="https://trwnh.com" rel="nofollow noopener noreferrer" target="_blank"><span class="invisible">https://</span><span class="">trwnh.com</span><span class="invisible"></span></a><br />help me live: <a href="https://liberapay.com/at" rel="nofollow noopener noreferrer" target="_blank"><span class="invisible">https://</span><span class="">liberapay.com/at</span><span class="invisible"></span></a> or <a href="https://paypal.me/trwnh" rel="nofollow noopener noreferrer" target="_blank"><span class="invisible">https://</span><span class="">paypal.me/trwnh</span><span class="invisible"></span></a></p><p>- my triggers are moths and glitter<br />- i have all notifs except mentions turned off, so please interact if you wanna be friends! i literally will not notice otherwise<br />- dm me if i did something wrong, so i can improve<br />- purest person on fedi, do not lewd in my presence<br />- #1 ami cole fan account</p><p>:fatyoshi:</p>',
'source': dict({
'fields': list([
dict({
'name': 'Website',
'value': 'https://trwnh.com',
'verified_at': '2019-08-29T04:14:55.571+00:00',
}),
dict({
'name': 'Sponsor',
'value': 'https://liberapay.com/at',
'verified_at': '2019-11-15T10:06:15.557+00:00',
}),
dict({
'name': 'Fan of:',
'value': "Punk-rock and post-hardcore (Circa Survive, letlive., La Dispute, THE FEVER 333)Manga (Yu-Gi-Oh!, One Piece, JoJo's Bizarre Adventure, Death Note, Shaman King)Platformers and RPGs (Banjo-Kazooie, Boktai, Final Fantasy Crystal Chronicles)",
'verified_at': None,
}),
dict({
'name': 'Main topics:',
'value': "systemic analysis, design patterns, anticapitalism, info/tech freedom, theory and philosophy, and otherwise being a genuine and decent wholesome poster. i'm just here to hang out and talk to cool people!",
'verified_at': None,
}),
]),
'follow_requests_count': 0,
'language': '',
'note': '''
i have approximate knowledge of many things. perpetual student. (nb/ace/they)
xmpp/email: a@trwnh.com
https://trwnh.com
help me live: https://liberapay.com/at or https://paypal.me/trwnh
- my triggers are moths and glitter
- i have all notifs except mentions turned off, so please interact if you wanna be friends! i literally will not notice otherwise
- dm me if i did something wrong, so i can improve
- purest person on fedi, do not lewd in my presence
- #1 ami cole fan account
:fatyoshi:
''',
'privacy': 'public',
'sensitive': False,
}),
'statuses_count': 33120,
'memorial': None,
'moved_to_account': None,
'mute_expires_at': None,
'noindex': False,
'note': '<p>i have approximate knowledge of many things. perpetual student. (nb/ace/they)</p><p>xmpp/email: a@trwnh.com<br /><a href="https://trwnh.com" target="_blank" rel="nofollow noopener" translate="no"><span class="invisible">https://</span><span class="">trwnh.com</span><span class="invisible"></span></a><br />help me live:<br />- <a href="https://donate.stripe.com/4gwcPCaMpcQ19RC4gg" target="_blank" rel="nofollow noopener" translate="no"><span class="invisible">https://</span><span class="ellipsis">donate.stripe.com/4gwcPCaMpcQ1</span><span class="invisible">9RC4gg</span></a><br />- <a href="https://liberapay.com/trwnh" target="_blank" rel="nofollow noopener" translate="no"><span class="invisible">https://</span><span class="">liberapay.com/trwnh</span><span class="invisible"></span></a></p><p>notes:<br />- my triggers are moths and glitter<br />- i have all notifs except mentions turned off, so please interact if you wanna be friends! i literally will not notice otherwise<br />- dm me if i did something wrong, so i can improve<br />- purest person on fedi, do not lewd in my presence</p>',
'role': None,
'roles': list([
]),
'source': None,
'statuses_count': 69523,
'suspended': None,
'uri': 'https://mastodon.social/users/trwnh',
'url': 'https://mastodon.social/@trwnh',
'username': 'trwnh',
}),
'instance': dict({
'configuration': dict({
'accounts': dict({
'max_featured_tags': 10,
'max_pinned_statuses': 4,
}),
'media_attachments': dict({
'image_matrix_limit': 16777216,
'image_size_limit': 10485760,
'supported_mime_types': list([
'image/jpeg',
'image/png',
'image/gif',
'image/heic',
'image/heif',
'image/webp',
'video/webm',
'video/mp4',
'video/quicktime',
'video/ogg',
'audio/wave',
'audio/wav',
'audio/x-wav',
'audio/x-pn-wave',
'audio/vnd.wave',
'audio/ogg',
'audio/vorbis',
'audio/mpeg',
'audio/mp3',
'audio/webm',
'audio/flac',
'audio/aac',
'audio/m4a',
'audio/x-m4a',
'audio/mp4',
'audio/3gpp',
'video/x-ms-asf',
]),
'video_frame_rate_limit': 60,
'video_matrix_limit': 2304000,
'video_size_limit': 41943040,
}),
'polls': dict({
'max_characters_per_option': 50,
'max_expiration': 2629746,
'max_options': 4,
'min_expiration': 300,
}),
'statuses': dict({
'characters_reserved_per_url': 23,
'max_characters': 500,
'max_media_attachments': 4,
}),
'translation': dict({
'enabled': True,
}),
'urls': dict({
'streaming': 'wss://mastodon.social',
}),
'vapid': dict({
'public_key': 'BCkMmVdKDnKYwzVCDC99Iuc9GvId-x7-kKtuHnLgfF98ENiZp_aj-UNthbCdI70DqN1zUVis-x0Wrot2sBagkMc=',
}),
}),
'contact': dict({
'account': dict({
'acct': 'Gargron',
'avatar': 'https://files.mastodon.social/accounts/avatars/000/000/001/original/dc4286ceb8fab734.jpg',
'avatar_static': 'https://files.mastodon.social/accounts/avatars/000/000/001/original/dc4286ceb8fab734.jpg',
'bot': False,
'created_at': '2016-03-16T00:00:00.000Z',
'discoverable': True,
'display_name': 'Eugen 💀',
'emojis': list([
]),
'fields': list([
dict({
'name': 'Patreon',
'value': '<a href="https://www.patreon.com/mastodon" target="_blank" rel="nofollow noopener noreferrer me"><span class="invisible">https://www.</span><span class="">patreon.com/mastodon</span><span class="invisible"></span></a>',
'verified_at': None,
}),
]),
'followers_count': 133026,
'following_count': 311,
'group': False,
'header': 'https://files.mastodon.social/accounts/headers/000/000/001/original/3b91c9965d00888b.jpeg',
'header_static': 'https://files.mastodon.social/accounts/headers/000/000/001/original/3b91c9965d00888b.jpeg',
'id': '1',
'last_status_at': '2022-10-31',
'locked': False,
'noindex': False,
'note': '<p>Founder, CEO and lead developer <span class="h-card"><a href="https://mastodon.social/@Mastodon" class="u-url mention">@<span>Mastodon</span></a></span>, Germany.</p>',
'statuses_count': 72605,
'url': 'https://mastodon.social/@Gargron',
'username': 'Gargron',
}),
'email': 'staff@mastodon.social',
}),
'api_versions': None,
'configuration': None,
'contact': None,
'description': 'The original server operated by the Mastodon gGmbH non-profit',
'domain': 'mastodon.social',
'languages': list([
'en',
]),
'registrations': dict({
'approval_required': False,
'enabled': False,
'message': None,
}),
'rules': list([
dict({
'id': '1',
'text': 'Sexually explicit or violent media must be marked as sensitive when posting',
}),
dict({
'id': '2',
'text': 'No racism, sexism, homophobia, transphobia, xenophobia, or casteism',
}),
dict({
'id': '3',
'text': 'No incitement of violence or promotion of violent ideologies',
}),
dict({
'id': '4',
'text': 'No harassment, dogpiling or doxxing of other users',
}),
dict({
'id': '5',
'text': 'No content illegal in Germany',
}),
dict({
'id': '7',
'text': 'Do not share intentionally false or misleading information',
}),
]),
'icon': None,
'languages': None,
'registrations': None,
'rules': None,
'source_url': 'https://github.com/mastodon/mastodon',
'thumbnail': dict({
'blurhash': 'UeKUpFxuo~R%0nW;WCnhF6RjaJt757oJodS$',
'url': 'https://files.mastodon.social/site_uploads/files/000/000/001/@1x/57c12f441d083cde.png',
'versions': dict({
'@1x': 'https://files.mastodon.social/site_uploads/files/000/000/001/@1x/57c12f441d083cde.png',
'@2x': 'https://files.mastodon.social/site_uploads/files/000/000/001/@2x/57c12f441d083cde.png',
}),
}),
'thumbnail': None,
'title': 'Mastodon',
'uri': 'mastodon.social',
'usage': dict({
'users': dict({
'active_month': 123122,
'active_month': 380143,
}),
}),
'version': '4.0.0rc1',
'version': '4.4.0-nightly.2025-02-07',
}),
})
# ---

View File

@ -28,7 +28,7 @@
'primary_config_entry': <ANY>,
'serial_number': None,
'suggested_area': None,
'sw_version': '4.0.0rc1',
'sw_version': '4.4.0-nightly.2025-02-07',
'via_device_id': None,
})
# ---

View File

@ -47,7 +47,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '821',
'state': '3169',
})
# ---
# name: test_sensors[sensor.mastodon_trwnh_mastodon_social_following-entry]
@ -98,7 +98,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '178',
'state': '328',
})
# ---
# name: test_sensors[sensor.mastodon_trwnh_mastodon_social_posts-entry]
@ -149,6 +149,6 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '33120',
'state': '69523',
})
# ---