Data¶
Everything socialchimp passes around is frozen: once made, it never changes.
A refresh produces a new Connection rather than editing the old one, and
anything holding a secret hides it from repr(). See
the tutorial for how these fit together.
Post¶
Post
dataclass
¶
Post(
text: str = "",
media: tuple[Media, ...] = (),
reply_to: str | None = None,
publish_at: datetime | None = None,
options: RawData = dict(),
)
Something to publish.
The fields here work on most networks. Anything that belongs to one
network only goes in options.
Attributes:
| Name | Type | Description |
|---|---|---|
text |
str
|
The words. Some networks call this a caption or a body. |
media |
tuple[Media, ...]
|
Pictures or videos to attach. |
reply_to |
str | None
|
Identifier of the post being replied to. |
publish_at |
datetime | None
|
When to publish, for networks that can schedule. Check
|
options |
RawData
|
Settings for one network only, such as Pinterest's
|
PostResult and PostState¶
PostResult
dataclass
¶
PostResult(
id: str,
url: str | None = None,
state: PostState = DONE,
raw: RawData = dict(),
cid: str | None = None,
)
What came back after publishing.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
str
|
The network's identifier for the new post. |
url |
str | None
|
Link to the post, where the network gives us one. |
state |
PostState
|
Whether the network has finished with it. |
raw |
RawData
|
The network's untouched reply, for anything we did not model. |
cid |
str | None
|
Bluesky's content hash for the new post. |
PostState
¶
Bases: Enum
How far along a post is.
Most networks finish while we wait. YouTube and TikTok keep working after
they accept the upload, so a post can come back as PROCESSING and finish
later. You hear about it through an update (see socialchimp.events).
SCHEDULED
class-attribute
instance-attribute
¶
The network accepted it and will publish it later.
PROCESSING
class-attribute
instance-attribute
¶
The network is still working on it, usually a video being encoded.
WAITING_FOR_PERSON
class-attribute
instance-attribute
¶
The network has finished, and now somebody has to tap a button.
TikTok can put a video in a person's drafts rather than posting it, so they can add their own caption and publish it themselves. Nothing is wrong and nothing more will happen on its own, so do not sit and wait for this one to change.
PostStats¶
How a published post is doing, in one shape for every network. What
account.read_stats(...) hands back. Every number may be None, which
means the network does not count that - never that it counted zero.
PostStats
dataclass
¶
PostStats(
id: str,
likes: int | None = None,
comments: int | None = None,
shares: int | None = None,
raw: RawData = dict(),
)
How a published post is doing.
Every number may be None, which means "this network does not count
that" - never "zero". A post nobody has liked and a network that keeps
no likes are two different answers, and only one of them is a number.
Networks all use their own words for these: Mastodon counts favourites and boosts, X counts likes and reposts. They arrive here under one set of names, so an app does not learn a vocabulary per network.
Only the numbers a network really publishes are here. Reach, impressions and clicks are deliberately missing: most networks do not give them out at all, and a field that could never be filled in reads like one that is always zero.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
str
|
The network's identifier for the post these numbers are about -
the same one |
likes |
int | None
|
How many people liked, favourited or reacted to it. |
comments |
int | None
|
How many replies it has. |
shares |
int | None
|
How many times it was passed on - boosted, reposted, reblogged, whichever word that network uses. |
raw |
RawData
|
The network's untouched reply, for any number we did not model. |
Media¶
Media
dataclass
¶
Media(
kind: MediaKind,
content: bytes | None = None,
path: Path | None = None,
url: str | None = None,
filename: str | None = None,
alt_text: str | None = None,
)
A picture or video to attach to a post.
Build one with from_file, from_bytes or from_url rather than calling
Media(...) directly - those work out the kind for you.
Attributes:
| Name | Type | Description |
|---|---|---|
kind |
MediaKind
|
Picture or video. |
content |
bytes | None
|
The bytes, when they were handed to us directly. |
path |
Path | None
|
Where the file lives on disk, read only when needed. |
url |
str | None
|
Where the file lives online. Some networks fetch it themselves; for the rest socialchimp downloads it first. |
filename |
str | None
|
Name to send along with the upload. |
alt_text |
str | None
|
Description for people using a screen reader. Worth setting. |
size
property
¶
How many bytes this is, when we can tell.
None for a file that is only a web address, because finding out
would mean downloading it - which is usually the thing a web address
was used to avoid.
Returns:
| Type | Description |
|---|---|
int | None
|
The size in bytes, or |
from_file
classmethod
¶
from_file(
path: str | Path,
*,
kind: MediaKind | None = None,
alt_text: str | None = None,
) -> Media
Attach a file from disk. It is read when the upload happens.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | Path
|
Where the file is. |
required |
kind
|
MediaKind | None
|
Picture or video. Worked out from the name if left out. |
None
|
alt_text
|
str | None
|
Description for screen readers. |
None
|
Returns:
| Type | Description |
|---|---|
Media
|
The media, ready to attach to a post. |
Source code in src/socialchimp/models.py
from_bytes
classmethod
¶
from_bytes(
content: bytes,
*,
filename: str,
kind: MediaKind | None = None,
alt_text: str | None = None,
) -> Media
Attach data you already hold in memory.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
content
|
bytes
|
The file's bytes. |
required |
filename
|
str
|
Name to send with the upload. Also used to work out the kind. |
required |
kind
|
MediaKind | None
|
Picture or video. Worked out from the name if left out. |
None
|
alt_text
|
str | None
|
Description for screen readers. |
None
|
Returns:
| Type | Description |
|---|---|
Media
|
The media, ready to attach to a post. |
Source code in src/socialchimp/models.py
from_url
classmethod
¶
Point at a file already online.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
Where the file is. It must be reachable by the network. |
required |
kind
|
MediaKind | None
|
Picture or video. Worked out from the address if left out. |
None
|
alt_text
|
str | None
|
Description for screen readers. |
None
|
Returns:
| Type | Description |
|---|---|
Media
|
The media, ready to attach to a post. |
Source code in src/socialchimp/models.py
piece
¶
Read part of the file.
Networks that take large video want it in pieces - YouTube, TikTok
and Facebook all do. Reading a piece at a time keeps a four gigabyte
video from becoming four gigabytes of memory, so use this rather
than slicing what read() gives you.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
start
|
int
|
How many bytes in to begin. |
required |
length
|
int
|
How many bytes to read. Fewer come back at the end of the file, which is how you know you have reached it. |
required |
Returns:
| Type | Description |
|---|---|
bytes
|
The bytes read. |
Raises:
| Type | Description |
|---|---|
InvalidPostError
|
If this media is only a web address. |
Source code in src/socialchimp/models.py
read
¶
Return the file's bytes.
Returns:
| Type | Description |
|---|---|
bytes
|
The content, read from disk if it is not already in memory. |
Raises:
| Type | Description |
|---|---|
InvalidPostError
|
If this media is only a URL. Download it first, or use a network that fetches URLs itself. |
Source code in src/socialchimp/models.py
MediaKind
¶
Bases: Enum
What sort of file is being attached.
Connection¶
Connection
dataclass
¶
Connection(
id: str,
platform: str,
host: str | None,
account_id: str,
account_name: str,
token: Token,
scopes: tuple[str, ...] = (),
extra: RawData = dict(),
avatar_url: str | None = None,
)
One social account someone has connected to your app.
This is the thing your app saves. socialchimp hands it to you; where and how you store it is entirely up to you.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
str
|
Your identifier for this connection. You choose it. |
platform |
str
|
Which network, for example |
host |
str | None
|
Which server, for networks that have more than one. |
account_id |
str
|
The identifier the network itself uses. |
account_name |
str
|
Something a person would recognise, shown in your UI. |
token |
Token
|
Current permission to act as this account. |
scopes |
tuple[str, ...]
|
What this token is allowed to do. |
extra |
RawData
|
Anything else one network needs, such as a Facebook page id or a YouTube channel id. |
avatar_url |
str | None
|
The account's picture, when the network gave one when it
was connected. Some networks put a short-lived address here,
which is why |
with_token
¶
with_token(token: Token) -> Connection
Return a copy of this connection carrying a new token.
Used after a refresh. The original is left alone.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
token
|
Token
|
The replacement token. |
required |
Returns:
| Type | Description |
|---|---|
Connection
|
A new |
Source code in src/socialchimp/models.py
Token¶
Token
dataclass
¶
Token(
access_token: str,
refresh_token: str | None = None,
expires_at: datetime | None = None,
refresh_token_expires_at: datetime | None = None,
)
Permission to act as someone on a social network.
Attributes:
| Name | Type | Description |
|---|---|---|
access_token |
str
|
The token used on every request. |
refresh_token |
str | None
|
Used to get a new access token. |
expires_at |
datetime | None
|
When the access token stops working. |
refresh_token_expires_at |
datetime | None
|
When the refresh token itself stops
working. |
refresh_token_is_expired
property
¶
Whether the refresh token has already run out.
True here means the person has to sign in again. There is nothing left to renew with.
expires_within
¶
Say whether this token runs out inside the next seconds.
Used to refresh early, before a request fails.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
seconds
|
float
|
How far ahead to look. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if the token expires within that window. Always False for a |
bool
|
token that does not expire. |
Source code in src/socialchimp/models.py
refresh_token_expires_within
¶
Say whether the refresh token runs out inside the next seconds.
Nothing socialchimp does can renew a refresh token, so this is not a warning to act on in code - it is a warning to show a person, far enough ahead that they can connect their account again before anything stops working. A week is a reasonable window.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
seconds
|
float
|
How far ahead to look. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if the refresh token expires within that window. Always |
bool
|
False where the network never told us, which is most of them. |
Source code in src/socialchimp/models.py
App credentials¶
What create_app and a manually-registered app store about themselves.
AppCredentials
dataclass
¶
Your app's own identity on one social network.
On most networks you create this by hand in a developer portal. On
Mastodon socialchimp can create it for you, and it has to be created
again for every server, because each Mastodon server is separate. That
is why host is part of the key.
Attributes:
| Name | Type | Description |
|---|---|---|
platform |
str
|
Which network, for example |
host |
str | None
|
Which server, for networks that have more than one. |
client_id |
str
|
Public half, given to you by the network. |
client_secret |
str
|
Private half. Never logged, never printed. |
The social inbox¶
What reading a post, its thread, its likes and its conversations hands back - added in 0.8.0. See the social inbox use case for working examples.
Page
dataclass
¶
Bases: Generic[T]
One page of results from a list call.
Every list call - reading likes, reading replies, reading conversations,
reading messages - takes after: str | None = None, limit: int | None =
None and hands one of these back.
Attributes:
| Name | Type | Description |
|---|---|---|
items |
tuple[T, ...]
|
What this page holds. |
next |
str | None
|
Pass this back as |
Person
dataclass
¶
Person(
id: str,
handle: str | None,
display_name: str | None,
avatar_url: str | None,
url: str | None,
raw: RawData = dict(),
)
Someone on a social network.
The author of a post, the person behind a like, the other side of a
conversation - all of them are a Person.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
str
|
The network's identifier for them - a Mastodon account id, a Bluesky DID, or a Meta PSID, IGSID or user id. |
handle |
str | None
|
Something like |
display_name |
str | None
|
The name they chose to show, when the network gives one. |
avatar_url |
str | None
|
Their picture, when the network gives one. |
url |
str | None
|
Their profile page, when the network has one. |
raw |
RawData
|
The network's untouched reply, for anything we did not model. |
PostDetails
dataclass
¶
PostDetails(
id: str,
cid: str | None,
url: str | None,
author: Person | None,
text: str,
html: str | None,
links: tuple[TextLink, ...],
attachments: tuple[Attachment, ...],
created_at: datetime | None,
visibility: Visibility | None,
parent_id: str | None,
root_id: str | None,
reply_count: int | None,
like_count: int | None,
repost_count: int | None,
quote_count: int | None,
liked_by_me: bool | None,
my_like_id: str | None,
is_mine: bool,
unavailable: Unavailable | None,
raw: RawData = dict(),
)
A post, read back in full - not just what publishing it returned.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
str
|
The network's identifier for it - a Mastodon status id, a
Bluesky |
cid |
str | None
|
Bluesky's content hash. |
url |
str | None
|
The permalink on the network's own website, when there is one. |
author |
Person | None
|
Who wrote it. |
text |
str
|
The words, as plain text. Mastodon's HTML is converted to
plain text here. Empty when |
html |
str | None
|
The network's own HTML, where it has one - Mastodon does. Untrusted: sanitise it yourself before showing it to anyone. |
links |
tuple[TextLink, ...]
|
The mentions, links and tags inside |
attachments |
tuple[Attachment, ...]
|
The pictures, videos and other files on this post. |
created_at |
datetime | None
|
When it was posted, according to the network. |
visibility |
Visibility | None
|
Who it was shared with. |
parent_id |
str | None
|
The post this one replies to, when it replies to one. |
root_id |
str | None
|
The top of the thread this post sits in. The same as |
reply_count |
int | None
|
How many replies it has. |
like_count |
int | None
|
How many people liked it. |
repost_count |
int | None
|
How many times it was reposted. |
quote_count |
int | None
|
How many times it was quoted. |
liked_by_me |
bool | None
|
Whether the connected account has liked it. |
my_like_id |
str | None
|
Bluesky's like-record uri for the connected account's
own like, when there is one. Pass it to |
is_mine |
bool
|
Whether the connected account wrote this post. |
unavailable |
Unavailable | None
|
Set when this is a placeholder standing in for a post a thread could not actually fetch, and says why. |
raw |
RawData
|
The network's untouched reply, for anything we did not model. |
Visibility
¶
Bases: Enum
Who a post was shared with.
None on PostDetails.visibility means the network has no such idea at
all - Bluesky and Meta do not model this the way Mastodon does.
PUBLIC
class-attribute
instance-attribute
¶
Shown to anyone, including people who do not follow the author.
UNLISTED
class-attribute
instance-attribute
¶
Public, but left out of public timelines and search. Mastodon only.
FOLLOWERS
class-attribute
instance-attribute
¶
Shown only to people who follow the author. Mastodon calls this
"private" on the wire; socialchimp uses the clearer word.
DIRECT
class-attribute
instance-attribute
¶
Shown only to the people mentioned in it. Mastodon calls this
"direct".
TextLink
dataclass
¶
TextLink(
start: int,
end: int,
kind: LinkKind,
target: str,
url: str | None,
)
A mention, a link or a tag, sitting inside PostDetails.text.
Attributes:
| Name | Type | Description |
|---|---|---|
start |
int
|
Where this link starts, as a Python string index into
|
end |
int
|
Where it ends, the same way. |
kind |
LinkKind
|
What sort of link this is. |
target |
str
|
What it points at: a URL for |
url |
str | None
|
A clickable address for this link, where one is known. |
LinkKind
¶
Attachment
dataclass
¶
Attachment(
kind: str,
url: str | None,
preview_url: str | None,
alt_text: str | None,
width: int | None,
height: int | None,
raw: RawData = dict(),
)
A picture, video or other file attached to a post.
Attributes:
| Name | Type | Description |
|---|---|---|
kind |
str
|
What sort of file this is - |
url |
str | None
|
Where to fetch the file, when the network gives one. |
preview_url |
str | None
|
A smaller version to show before the full file loads, when the network gives one. |
alt_text |
str | None
|
A description for people using a screen reader, when the author wrote one. |
width |
int | None
|
The file's width in pixels, when known. |
height |
int | None
|
The file's height in pixels, when known. |
raw |
RawData
|
The network's untouched reply, for anything we did not model. |
Unavailable
¶
Bases: Enum
Why a post that should be here could not be shown.
Set on a PostDetails standing in for a post a thread could not
actually fetch - a placeholder rather than the real thing.
Thread
dataclass
¶
Thread(
post: PostDetails,
replies: tuple[PostDetails, ...],
complete: bool,
raw: RawData = dict(),
)
A post together with its replies.
Attributes:
| Name | Type | Description |
|---|---|---|
post |
PostDetails
|
The post that was asked for. |
replies |
tuple[PostDetails, ...]
|
Every reply read back, flat and oldest first. Build the
tree yourself by matching each one's |
complete |
bool
|
|
raw |
RawData
|
The network's untouched reply, for anything we did not model. |
Like
dataclass
¶
Like(
person: Person,
liked_at: datetime | None,
raw: RawData = dict(),
)
One person's like on a post.
Attributes:
| Name | Type | Description |
|---|---|---|
person |
Person
|
Who liked it. |
liked_at |
datetime | None
|
When they liked it. Bluesky has this; Mastodon never does,
so it is always |
raw |
RawData
|
The network's untouched reply, for anything we did not model. |
LikeResult
dataclass
¶
What came back after liking a post.
Attributes:
| Name | Type | Description |
|---|---|---|
post_id |
str
|
The post that was liked. |
like_id |
str | None
|
Bluesky's like-record uri, worth keeping so |
raw |
RawData
|
The network's untouched reply, for anything we did not model. |
Conversation
dataclass
¶
Conversation(
id: str,
people: tuple[Person, ...],
last_message: Message | None,
unread_count: int | None,
updated_at: datetime | None,
can_reply_until: datetime | None,
full_history: bool,
raw: RawData = dict(),
)
A direct message conversation with one or more people.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
str
|
The network's identifier for this conversation. |
people |
tuple[Person, ...]
|
Everyone in it except the connected account. |
last_message |
Message | None
|
The most recent message, when there is one to show. |
unread_count |
int | None
|
How many messages are unread. Mastodon only says yes
or no, so it reports |
updated_at |
datetime | None
|
When this conversation last changed. |
can_reply_until |
datetime | None
|
Meta's 24-hour window to reply closes at this
moment. |
full_history |
bool
|
|
raw |
RawData
|
The network's untouched reply, for anything we did not model. |
Message
dataclass
¶
Message(
id: str,
conversation_id: str,
sender: Person,
text: str,
sent_at: datetime,
is_mine: bool,
deleted: bool,
attachments: tuple[Attachment, ...],
raw: RawData = dict(),
)
One message inside a Conversation.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
str
|
The network's identifier for this message. |
conversation_id |
str
|
Which conversation it belongs to. |
sender |
Person
|
Who sent it. |
text |
str
|
The words. Empty when |
sent_at |
datetime
|
When it was sent. |
is_mine |
bool
|
Whether the connected account sent it. |
deleted |
bool
|
Whether it has been deleted since. |
attachments |
tuple[Attachment, ...]
|
Pictures, videos or other files sent with it. |
raw |
RawData
|
The network's untouched reply, for anything we did not model. |