skyter app

App

class skyter.app.MainApp(credentials: tuple | None = None, settings: Settings = Settings(initial_source=FeedSource(target=None, feed_type='timeline', params={}), page_limit=20, default_pds=None, search_language=None, relative_dates=True, show_footer=True, notification_check_interval=60, feed_new_items_check_interval=60, feed_new_items_action='alert', subscribed_labels=True, hide_metrics=False, file_picker_location='.', open_cmds={'images': None, 'video': None, 'external_link': None}, path=PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/skyter/checkouts/latest/skyter/data/settings.json')), pds: str | None = None, **kwargs)

Bases: App

CSS_PATH = 'styles.tcss'

File paths to load CSS from.

NOTIFICATION_TIMEOUT = 2

Default number of seconds to show notifications before removing them.

action_command_palette()

Store app focus before launching command palette.

action_open_settings()

Open settings screen

get_system_commands(screen: Screen) Iterable[SystemCommand]

Add actions to the command palette.

on_logged_in(message: LoggedIn) None

Push main app screen on login

async on_mount() None

Set title and focus feed on mount

async on_post_submitted(message: PostSubmitted) None

Make client call with data received from post compose

update_settings()

Updates app attributes from settings

Login

class skyter.login.LoggedIn

Bases: Message

Custom message sent when login is successful.

handler_name: ClassVar[str] = 'on_logged_in'

Name of the default message handler.

class skyter.login.LoginForm(*children: Widget, name: str | None = None, id: str | None = None, classes: str | None = None, disabled: bool = False, markup: bool = True)

Bases: Widget

Form widget to enter credentials

async handle_login() None

Handle login button press.

async on_button_pressed(event: Pressed) None

Handle button press events.

async on_input_submitted(event: Submitted) None

Handle when text is submitted in an input field.

class skyter.login.LoginScreen(name: str | None = None, id: str | None = None, classes: str | None = None)

Bases: Screen

Login screen

class skyter.login.Title(name: str, **kwargs)

Bases: Widget

Render app title in figlet font

Settings

class skyter.settings.EditSettings(settings: Settings, **kwargs)

Bases: Widget

Widget containing the editable JSON settings

action_close_screen() None

Action for closing the screen.

action_save_settings() None

Action for saving settings.

check_valid_json()

Check if text area contains valid JSON

on_button_pressed(event: Pressed) None

Handle save and cancel button presses

class skyter.settings.Settings(initial_source: FeedSource = <factory>, page_limit: int = 20, default_pds: str | None = None, search_language: str | None = None, relative_dates: bool = True, show_footer: bool = True, notification_check_interval: int | None = 60, feed_new_items_check_interval: int | None = 60, feed_new_items_action: str | None = 'alert', subscribed_labels: bool = True, hide_metrics: bool = False, file_picker_location: str = '.', open_cmds: dict = <factory>, path: Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/skyter/checkouts/latest/skyter/data/settings.json'))

Bases: object

Data class for accessing app settings

classmethod from_json(filepath: Path | str | None = None) Settings

Create data class object from json file if it exists.

get_json()

Returns a JSON string representation of the data class

to_json() None

Write data class object to json file

update_from_json_string(json_str: str)

Updates the data class from JSON string

class skyter.settings.SettingsScreen(settings: Settings, **kwargs)

Bases: ModalScreen

Settings config screen

Main Screen

class skyter.main_screen.MainScreen(client: BlueSkyClient, source: FeedSource = FeedSource(target=None, feed_type='timeline', params={}), **kwargs)

Bases: Screen

Main app screen

action_build_block_list() None

Action to build blocked users feed.

action_build_custom_feed(uri: str, feed_name: str) None

Action to build post feed for custom feed

action_build_follower_list(handle: str | None = None) None

Action to build user followers feed. If no handle is specified, get own followers.

action_build_follows_list(handle: str | None = None) None

Action to build user follows feed. If no handle is specified, get own follows.

action_build_home() None

Action to build feed from initial source defined in settings

action_build_likes(uri: str, title_params: dict) None

Action to build feed for likers of a post

action_build_list_feed(uri: str, feed_name: str) None

Action to build post feed for list

action_build_list_people(uri: str, feed_name: str) None

Action to build user feed of users included in list

action_build_mentions()

Action to build notifications feed, showing only mentions.

action_build_mute_list() None

Action to build muted users feed.

action_build_notifications()

Action to build notifications feed.

action_build_quotes(uri: str, title_params: dict) None

Action to build feed for quotes of a post

action_build_reposts(uri: str, title_params: dict) None

Action to build feed for reposters of a post

action_build_tag_result(query: str)

Action to fill search form and conduct to search for a given query, e.g., after clicking a hashtag.

action_build_thread(uri: str, title_params: dict) None

Action to build post thread feed

action_build_timeline() None

Action to build following timeline

action_build_user_feed(handle: str | None = None, params: dict | None = None) None

Action to build user feed. If no handle is specified, get own profile.

action_build_user_likes(handle: str | None = None) None

Action to build user liked posts feed. If no handle is specified, get own likes.

action_build_user_lists(handle: str | None = None) None

Action to build list feed of lists created by user

action_build_user_starter_packs(handle: str | None = None) None

Action to build starter packs feed

action_hide_edge_panels()

Hide all edge panels

action_next_feed() None

Action to return to next opened feed

action_open_post_compose(reference: Post | None = None, post_type: str | None = None) None

Action to open post compose screen.

action_pause_notifications() None

Action to disable header notification count display and client API calls

action_previous_feed() None

Action to return to previous opened feed

action_resume_notifications() None

Action to re-enable header notification count display and client API calls

action_toggle_search_panel()

Action to toggle search edge panel

async build_profile_panel(handle: str | None = None)

Make query for user profile data and update profile view edge panel.

check_action(action: str, parameters: tuple[object, ...]) bool | None

Override default method to check if an action should be available.

check_notifications() None

Worker to periodically check for new notifications and update title header

get_saved_feeds()

Action to build feed of saved feeds.

get_suggested_feeds()

Action to build feed of suggested feeds by passing empty feed search.

log_out()

Action to log out user and load log-in modal

offer_screen_commands() Iterable[SystemCommand]

Add actions to the app’s command palette.

async on_mount() None

Set title, focus feed, add timers on mount

on_search_submitted(event: SearchSubmitted) None

Handle when search is submitted

Search based on existing values in the search view form.

async reset_feed(source: FeedSource) None

Action to rebuild the feed based on source, changing feed type if necessary

async restore_feed()

Restore feed from stored feed state data

show_edge_panel(panel_name)

Show an edge panel by id

store_current_feed_state() None

Update feed stack with current feed state

async update_notification_count() int

Make query to get unread notification count. Returns number of new notifications

update_title(new_available=False) None

Create app title header

Feeds

class skyter.feeds.container.FeedViewContainer(client: BlueSkyClient, source: FeedSource, **kwargs)

Bases: Container

Container for remounting different FeedView types

async change_feed(source: FeedSource) None

Handle feed switching

async reload_feed(state: dict) None

Switch feed using stored feed state

class skyter.feeds.feed.FeedPanel(*children: Widget, name: str | None = None, id: str | None = None, classes: str | None = None, disabled: bool = False, markup: bool = True)

Bases: Widget

Abstract class for panel items in feeds

class skyter.feeds.feed.FeedView(client: BlueSkyClient, source: FeedSource, mount_empty: bool = False, **kwargs)

Bases: ListView

ListView for atproto feeds.

class Listed(data_obj: Any, **kwargs)

Bases: ListItem

ListItem container to list FeedPanel objects in FeedView object

swap_data(data_obj: Any)

Change data object and trigger recompose

async action_cursor_up() None

When already on first index, up will fetch new items

action_scroll_bottom()

Scroll to bottom of feed and highlight last item

action_scroll_top()

Scroll to top of feed and highlight first item

action_toggle_auto_update()

Action to toggle automatic updates when new feed items are available

action_view_timeline() None

Request the app to build the following timeline.

async check_new_available() None

Check if new items are available and if so disable monitor and display indicator

async create_list_items(items: list[dict]) list

Create Listed objects from list of dictionaries

async more_items(reset_pagination: bool = False) None

Fetch data and add more Listed items to the feed

async new_items(auto_fetched: bool = False) None

Fetch new data and add more Listed items to top of the feed

new_monitor() None

Worker to monitor new feed items

offer_widget_commands() Iterable[SystemCommand]

Add actions to the app’s command palette.

async on_list_view_highlighted(event: Highlighted) None

Request more items when last item is highlighted

async on_mount()

Get initial items once mounted

async refresh_from_data(feed_data: list, paginator: FeedPaginator, idx: int)

Refresh feed from a stored feed state

async refresh_items()

Refresh feed and reset pagination.

class skyter.feeds.posts.PostFeedView(client: BlueSkyClient, source: FeedSource, mount_empty: bool = False, **kwargs)

Bases: FeedView, UserActions

FeedView for post-based feeds.

class Listed(data_obj: Any, **kwargs)

Bases: Listed

Custom ListItem container to list PostPanel objects in PostFeedView

show_post_deleted() None

Change post panel child to deleted post panel

class MissingPostPanel(post: MissingPost, is_quote: bool = False, **kwargs)

Bases: FeedPanel

class PostPanel(post: Post, is_quote: bool = False, **kwargs)

Bases: FeedPanel

Feed panel for rendering post content

class PostExternalEmbed(external_link: dict, **kwargs)

Bases: Widget

Widget that renders post external links.

class PostInnerSubtitle(subtitle: Text, **kwargs)

Bases: Widget

Widget that renders subtitle content inside panel borders.

class PostMediaPanel(media_item: dict, media_type: str, display_media: bool = False, **kwargs)

Bases: Widget

Container for post media

class PostMediaAlt(media_item: dict, media_type: str, **kwargs)

Bases: Widget

Widget that renders post image and video alt text.

class PostPanelContent(post_content: str, style: str | None = None, **kwargs)

Bases: Widget

Widget that renders post content.

build_subtitle(reply_count: int, repost_count: int, quote_count: int, like_count: int, liked: str | None, reposted: str | None)

Build panel subtitle

build_title(display_name: str, handle: str, created_at: str, blocking: bool = False, muted: bool = False)

Build panel title

class PostPanelLabel(post: Post, blur: list, **kwargs)

Bases: Widget

Widget that renders label alongside or in place of content.

class ThreadContextPanel(post: ThreadContext, **kwargs)

Bases: FeedPanel

Action to copy the highlighted post’s embedded external link.

Action to copy the URLs of the highlighted post’s images.

action_copy_post_link() None

Action to copy the URL of the highlighted post.

action_copy_post_text() None

Action to copy the text of the highlighted post.

action_copy_uri() None

Action to copy the uri of the highlighted post.

Action to copy the highlighted post’s video URL.

action_delete() None

Action to delete the highlighted post if own post

action_handle_block() None

Action to block the author of the highlighted post.

action_handle_follow() None

Action to follow the author of the highlighted post.

action_handle_like() None

Action to like/unlike the highlighted post

action_handle_mute_profile() None

Action to mute the author of the highlighted post.

action_handle_repost() None

Action to repost/undo repost of the highlighted post

action_load_embedded_feed() None

Request the app to rebuild the feed based on highlighted post’s embedded starter pack

action_open_embedded() None

Action to open the highlighted post’s embedded content (image, video, link, quoted post, feed)

Action to open the highlighted post’s embedded external link.

Action to open the URLs of the highlighted post’s images.

Action to open the highlighted post’s video. If no video command is defined in settings, will open post URL in browser.

action_quote() None

Action to open the quote compose dialog for the highlighted post

action_reply() None

Action to open the reply compose dialog for the highlighted post

action_show_blurred_content() None

Action to show content behind content/media blur label

action_show_followers()

Action to show followers of highlighted post author.

action_show_follows()

Action to show follows of highlighted post author.

action_show_lists()

Action to show lists of highlighted post author.

action_show_user_likes()

Action to show likes of highlighted post author.

action_view_likes() None

Request the app to build feed for likes of highlighted post

action_view_list_users() None

Request the app to build list people feed for highlighted post’s embedded starter pack or list

action_view_profile() None

Request the app to build user feed for highlighted post author

action_view_quoted() None

Action to view thread of quoted post of highlighted post.

action_view_quotes() None

Request the app to build feed for quotes of highlighted post

action_view_reposts() None

Request the app to build feed for reposts of highlighted post

action_view_thread() None

Request the app to build thread for highlighted post

action_view_user_posts() None

Action to show posts and author threads for user post feed

action_view_user_replies() None

Action to show posts and replies for user post feed

check_action(action: str, parameters: tuple[object, ...]) bool | None

Override default method to check if an action should be available.

async create_list_items(items: list[dict]) list[Listed]

Create Listed objects from list of dictionaries

async generate_data(new_items: bool = False, reset_pagination: bool = False)

Make client calls to retrieve data for building feed.

offer_widget_commands() Iterable[SystemCommand]

Add actions to the app’s command palette.

class skyter.feeds.thread.ThreadFeedView(client: BlueSkyClient, source: FeedSource, mount_empty: bool = False, **kwargs)

Bases: PostFeedView

Override certain PostFeedView methods and change keybindings for thread view.

async generate_data(new_items: bool = False, reset_pagination: bool = False)

Make client calls to retrieve data for building feed.

on_list_view_highlighted(event: Highlighted) None

Override parent action to fetch more data on last index for feeds without pagination.

async on_mount(event: Mount)

Override parent method and scroll to main post

async refresh_items()

Override parent method and scroll to main post

class skyter.feeds.users.UserFeedView(client: BlueSkyClient, source: FeedSource, mount_empty: bool = False, **kwargs)

Bases: FeedView, UserActions

FeedView for user-based feeds (i.e., user search results)

class Listed(data_obj: Any, **kwargs)

Bases: Listed

Custom ListItem container to list UserPanel objects in UserFeedView

class UserPanel(user: User, **kwargs)

Bases: FeedPanel

Feed panel for rendering user information

build_body()

Build panel body text

build_subtitle()

Build panel subtitle

build_title()

Build panel title

Action to copy the URL of the highlighted user.

async action_handle_block() None

Action to block the highlighted user.

async action_handle_follow() None

Action to follow the highlighted user.

async action_handle_mute_profile() None

Action to mute the highlighted user.

action_view_profile() None

Request the app to build user feed for highlighted user

check_action(action: str, parameters: tuple[object, ...]) bool | None

Override default method to check if an action should be available.

async create_list_items(items: list[dict]) list[Listed]

Create Listed objects from list of dictionaries

async generate_data(new_items: bool = False, reset_pagination: bool = False)

Make client calls to retrieve data for building feed.

offer_widget_commands() Iterable[SystemCommand]

Add actions to the app’s command palette.

class skyter.feeds.notifications.NotificationFeedView(client: BlueSkyClient, source: FeedSource, mount_empty: bool = False, **kwargs)

Bases: FeedView, UserActions

FeedView for custom feed-based feeds (i.e., feed search results, suggested feeds)

class FollowNotificationPanel(notification: Notification, **kwargs)

Bases: NotificationPanel

Feed panel for rendering follow notification information

build_body()

Build panel content

build_subtitle()

Build panel subtitle

build_title()

Build panel title

class Listed(data_obj: Any, **kwargs)

Bases: Listed

Custom ListItem container to list UserPanel objects in UserFeedView

class MentionNotificationPanel(notification: Notification, **kwargs)

Bases: NotificationPanel

Feed panel for rendering reply notification information

build_body()

Build panel content

build_subtitle()

Build panel subtitle

build_title()

Build panel title

class NotificationPanel(notification: Notification, **kwargs)

Bases: FeedPanel

Feed panel for rendering notification information. Title, subtitle and body methods should be overridden by child classes.

build_title()

Build panel title

class PostInteractionNotificationPanel(notification: Notification, **kwargs)

Bases: NotificationPanel

Feed panel for rendering like and repost notification information

build_body()

Build panel content

build_subtitle()

Build panel subtitle

build_title()

Build panel title

async action_handle_block() None

Action to block the profile of the highlighted notification.

async action_handle_follow() None

Action to follow the profile of the highlighted notification.

async action_handle_mute_profile() None

Action to mute the profile of the highlighted notification.

action_view_mentions() None

Action to show mentions / all notifications.

action_view_notifications() None

Action to show all notifications.

action_view_profile() None

Request the app to build user feed for highlighted user

check_action(action: str, parameters: tuple[object, ...]) bool | None

Override default method to check if an action should be available.

async create_list_items(items: list[dict]) list[Listed]

Create Listed objects from list of dictionaries

async generate_data(new_items: bool = False, reset_pagination: bool = False)

Make client calls to retrieve data for building feed.

offer_widget_commands() Iterable[SystemCommand]

Add actions to the app’s command palette.

on_list_view_highlighted(event: Highlighted) None

Mark unread notifications as read when highlighted

class skyter.feeds.custom_feeds.CustomFeedPanel(cust_feed: CustomFeed, is_embedded: bool = False, **kwargs)

Bases: FeedPanel

Feed panel for rendering custom feed information

build_subtitle()

Build panel subtitle

build_title()

Build panel title

class skyter.feeds.custom_feeds.CustomFeedView(client: BlueSkyClient, source: FeedSource, mount_empty: bool = False, **kwargs)

Bases: FeedView

FeedView for custom feed-based and list-based feeds (i.e., feed search results, suggested feeds, saved feeds, lists)

class Listed(data_obj: Any, **kwargs)

Bases: Listed

Custom ListItem container to list CustomFeedPanel objects in CustomFeedView

action_copy_uri() None

Action to copy the uri of the highlighted post.

action_load_feed() None

Request the app to rebuild the feed based on highlighted custom feed/list.

action_save_feed() None

Save highlighted custom feed

action_unsave_feed() None

Unsave highlighted custom feed

action_view_profile() None

Request the app to build user feed for highlighted feed author

action_view_users() None

Request the app to build list people feed for highlighted list

check_action(action: str, parameters: tuple[object, ...]) bool | None

Override default method to check if an action should be available.

async create_list_items(items: list[dict]) list[Listed]

Create Listed objects from list of dictionaries

async generate_data(new_items: bool = False, reset_pagination: bool = False)

Make client calls to retrieve data for building feed.

offer_widget_commands() Iterable[SystemCommand]

Add actions to the app’s command palette.

on_list_view_highlighted(event: Highlighted) None

Override parent action to fetch more data on last index for feeds without pagination.

class skyter.feeds.starter_packs.StarterPackFeedView(client: BlueSkyClient, source: FeedSource, mount_empty: bool = False, **kwargs)

Bases: FeedView

FeedView for starter pack feeds

class Listed(data_obj: Any, **kwargs)

Bases: Listed

Custom ListItem container to list StarterPackPanel objects in StarterPackFeedView

action_copy_uri() None

Action to copy the uri of the highlighted post.

action_load_feed() None

Request the app to rebuild the feed based on highlighted custom feed/list.

action_view_profile() None

Request the app to build user feed for highlighted feed author

action_view_users() None

Request the app to build list people feed for highlighted starter pack

async create_list_items(items: list[dict]) list[Listed]

Create Listed objects from list of dictionaries

async generate_data(new_items: bool = False, reset_pagination: bool = False)

Make client calls to retrieve data for building feed.

offer_widget_commands() Iterable[SystemCommand]

Add actions to the app’s command palette.

class skyter.feeds.starter_packs.StarterPackPanel(starter_pack: StarterPack, is_embedded: bool = False, **kwargs)

Bases: FeedPanel

Feed panel for rendering starter pack information.

build_subtitle()

Build panel subtitle

build_title()

Build panel title

Profile

class skyter.profile.ProfileView(client: BlueSkyClient, handle: str | None = None, **kwargs)

Bases: Widget, UserActions

Panel for showing profile data

Action to copy the URL of the profile.

async action_handle_block()

Action to block/unblock user

async action_handle_follow()

Action to follow/unfollow user

async action_handle_mute()

Action to mute/unmute user

async action_refresh_panel(handle: str | None = None, refresh_data: bool = True)

Refresh the panel, optionally setting a new handle.

action_show_followers()

Action to show user’s followers.

action_show_follows()

Action to show user’s follows.

action_show_likes()

Action to show user’s lists.

action_show_lists()

Action to show user’s lists.

action_show_starter_packs()

Action to show user’s lists.

check_action(action: str, parameters: tuple[object, ...]) bool | None

Override default method to check if an action should be available.

offer_widget_commands() Iterable[SystemCommand]

Add actions to the app’s command palette.

on_blur() None

Manually remove focused class for default non-focusable widget

on_focus() None

Manually add focused class for default non-focusable widget

Search

class skyter.search.SearchSubmitted(query: str, params: dict)

Bases: Message

Custom message sent when search is submitted.

handler_name: ClassVar[str] = 'on_search_submitted'

Name of the default message handler.

class skyter.search.SearchView(**kwargs)

Bases: Widget

Panel for conducting search with search bar and search options.

Handle when text is submitted in an input field.

on_button_pressed(event: Pressed) None

Handle button press events.

on_input_submitted(event: Submitted) None

Handle when text is submitted in an input field.

on_select_changed(event: Changed) None

Handle when select search type is changed and disable/enable applicable form fields.

reset(query: str | None = None)

Reset form to default values, optionally setting search bar value.

Compose

class skyter.compose.compose.ComposeWidget(reference: Post | str | None = None, **kwargs)

Bases: Static

Common methods for text composition

action_close_screen() None

Action for closing the compose screen.

on_text_area_changed(event: Changed) None

Handle text area changes to update character counter.

update_char_counter(counter: Static, button: Button, empty_ok_when: callable = None)

Check text against char limit and modify button state.

class skyter.compose.post_compose.PostComposeScreen(reference: Post | None = None, post_type: str | None = None, **kwargs)

Bases: ModalScreen

Post compose screen

class skyter.compose.post_compose.PostComposeWidget(post_type: str = 'post', **kwargs)

Bases: ComposeWidget

Widget containing a text area for composing post content

class EmbedLabel(media_item: dict, **kwargs)

Bases: Label

Common methods for labels displaying embedded content

action_remove_embed()

Action to remove widget and delete stored media from parent

on_blur() None

Manually remove focused class for default non-focusable widget

on_focus() None

Manually add focused class for default non-focusable widget

class LinkLabel(media_item: dict, **kwargs)

Bases: EmbedLabel

Label to display external link embed

class MediaFileLabel(media_item: dict, **kwargs)

Bases: EmbedLabel

Label to display attached media file

action_edit_alt() None

Action to edit alt text associated with an attached media file

class ReferencePostEmbed(post: Post, **kwargs)

Bases: Widget

Content of original post being replied to or quoted

action_submit_post() None

Action for submitting post.

check_char_limit() None

Update character counter display and submit button state.

check_has_media() bool

Check if there is currently media attached to the post

check_submit_allowed() bool

Check if post submission is allowed

async handle_file_selector(media_type: str) None

Get file path from file selector screen

Get form response from link add screen

on_button_pressed(event: Pressed) None

Handle submit and cancel button presses

update_media_buttons()

Enable or disable media buttons, based on media currently attached to post

class skyter.compose.post_compose.PostSubmitted(text: str, post_type: str, media: dict, reference_uri: str | None = None)

Bases: Message

Custom message sent when post is submitted.

handler_name: ClassVar[str] = 'on_post_submitted'

Name of the default message handler.

class skyter.compose.link.LinkAddWidget(**kwargs)

Bases: Widget

Widget containing a form for embedded link data

action_close_screen() None

Action for closing the screen.

Save link data and exit screen

async handle_url_submitted(url: str | None = None)

Read meta information from URL and populate form

on_button_pressed(event: Pressed) None

Handle save and cancel button presses

async on_input_submitted(event: Submitted) None

Handle when text is submitted in URL input field.

class skyter.compose.media.AltComposeScreen(media_item: dict, **kwargs)

Bases: ModalScreen

Alt text compose screen

class skyter.compose.media.AltComposeWidget(alt: str | None = None, **kwargs)

Bases: ComposeWidget

Widget containing a text area for composing alt text

action_save_alt() None

Save alt text and exit screen

check_char_limit() None

Update character counter display and submit button state.

on_button_pressed(event: Pressed) None

Handle save and cancel button presses

class skyter.compose.media.MediaOpen(media_type: str, **kwargs)

Bases: FileOpen

File picker screen for attaching image and video files

User Actions

class skyter.user_actions.UserActions

Bases: object

Collection of methods to handle user-based library calls to mixin with other classes. Child classes must have self.client.

async _user_action_block(handle: str, blocking: str, following: str, followers_count: int | None = None) bool

Action to block/unblock user

async _user_action_follow(handle: str, following: str, followers_count: int | None = None) dict

Action to follow/unfollow user

async _user_action_mute(handle: str, muted: bool) bool

Action to mute/unmute user

UI

class skyter.ui.BreakpointContainer(*children: Widget, name: str | None = None, id: str | None = None, classes: str | None = None, disabled: bool = False, markup: bool = True)

Bases: Container

Container class with vertical/horizontal layout determined by breakpoints. Layout set in CSS file.

class skyter.ui.SplitTitlePanel(renderable='', *, left_title: Text | None = None, right_title: Text | None = None, **kwargs)

Bases: Panel

Rich Panel class with ability to set simultaneous left aligned and right aligned titles.

Utilities

skyter.utils.abbrev_num(n: int)

Converts integer to abbreviated string with 1 decimal accuracy.

skyter.utils.extract_tags_and_handles(text: str) Text

Convert instances of hashtags and handles in string to clickable links

skyter.utils.get_month_year(timestamp: str)

Converts an ISO 8601 UTC timestamp to Month Year.

async skyter.utils.get_url_meta(url: str) dict

Retrieve meta information from a URL.

Parameters:
  • url (str) – The URL to fetch meta information from

  • timeout (int) – Request timeout in seconds (default: 10)

Returns:

β€˜title’, β€˜description’, β€˜image’, β€˜url’

Return type:

Dict with keys

Converts handle into clickable link that loads profile

skyter.utils.remove_bidi_controls(text: str) str

Remove Unicode bidirectional control characters

skyter.utils.time_since(timestamp: str) str

Converts an ISO 8601 UTC timestamp to a human-readable relative time string like β€˜2h’ or β€˜3d’.

skyter.utils.time_str(timestamp: str) str

Converts an ISO 8601 UTC timestamp to a human-readable localized time string like β€˜May 4 2025 at 1:03PM’.

skyter.utils.validate_url(url: str) str

Validate whether string is a well-formed URL and see if exists

Parameters:

url (str) – The URL to validate

Returns:

URL with protocol if valid, otherwise None

Data classes

class skyter.data_classes.CustomFeed(uri: str | None, item_type: str, cid: str | None, display_name: str, avatar: str | None, description: str | None, like_count: int | None, item_count: int | None, liked: str | None, pinned: bool | None, creator: dict | None)

Bases: object

Data class for listed items in CustomFeedView.

classmethod from_dict(d: dict) CustomFeed

Create data class object from dictionary

class skyter.data_classes.FeedSource(target: str | None = None, feed_type: str = 'timeline', params: dict[str, ~typing.Any]=<factory>)

Bases: object

Data class for defining FeedView object source. Used to determine FeedView class, widget title, library methods to use.

feedview_title()

Return widget title based on feedview type and target

feedview_type()

Return FeedView class to be used based on feed type and parameters

class skyter.data_classes.MissingPost(uri: str, is_deleted: bool, reply_position: str | None)

Bases: object

Data class for blocked/deleted posts in PostFeedView

classmethod from_dict(d: dict) MissingPost

Create data class object from dictionary

class skyter.data_classes.Notification(uri: str, cid: str, reason: str, reason_subject: str, subject: dict | None, record: dict | None, handle: str, display_name: str | None, description: str | None, is_read: bool, created_at: str, following: str | None, followed_by: str | None, muted: bool, blocking: str | None, blocked_by: bool)

Bases: object

Data class for listed items in NotificationFeedView.

classmethod from_dict(d: dict)

Create data class object from dictionary

class skyter.data_classes.Post(uri: str, cid: str, display_name: str, handle: str, muted: bool, blocked_by: bool, post_content: str, created_at: str, reply_count: int = 0, repost_count: int = 0, quote_count: int = 0, like_count: int = 0, liked: str | None = None, reposted: str | None = None, media: dict | None = None, reply_position: str | None = None, thread_main_post: bool = False, reason: str | None = None, repost: dict | None = None, following: str | None = None, followed_by: str | None = None, blocking: str | None = None, author_labels: list = <factory>, labels: list = <factory>, content_blur: list = <factory>, media_blur: list = <factory>, information_labels: list = <factory>, blurred: bool = False)

Bases: object

Data class for listed items in PostFeedView.

classmethod from_dict(d: dict) Post

Create data class object from dictionary

Check whether the post has an embedded external link

has_feed()

Check whether the post has an embedded feed

has_images()

Check whether the post has embedded images

has_list()

Check whether the post has an embedded list

has_quote()

Check whether the post has an embedded quote

has_starter_pack()

Check whether the post has an embedded starter pack

has_video()

Check whether the post has an embedded video

class skyter.data_classes.StarterPack(uri: str, cid: str, list_uri: str, display_name: str, description: str | None, joined_count: int, creator: dict)

Bases: object

Data class for listed items in StarterPackFeedView.

classmethod from_dict(d: dict) StarterPack

Create data class object from dictionary

class skyter.data_classes.ThreadContext(uri: str, handle: str, post_content: str | None)

Bases: object

Data class representing gap between parent and root replies in PostFeedView

classmethod from_dict(d: dict) ThreadContext

Create data class object from dictionary

class skyter.data_classes.User(did: str, handle: str, display_name: str | None, description: str | None, avatar: str, banner: str | None, created_at: str, following: str | None, followers_count: int | None, known_followers_count: int | None, follows_count: int | None, posts_count: int | None, followed_by: str | None, muted: bool, mute_list: str | None, blocking: str | None, blocking_by_list: str | None, blocked_by: bool, verification: Any | None, labels: list, badges: list | None)

Bases: object

Data class for ProfileView and listed items in UserFeedView.

classmethod from_dict(d: dict) User

Create data class object from dictionary