Rename toot to witchie

This commit is contained in:
Ngô Ngọc Đức Huy 2023-12-12 10:24:20 +07:00
parent 1c5abb8419
commit 41fff21b8d
Signed by: xarvos
GPG key ID: 904AF1C7CDF695C3
36 changed files with 157 additions and 166 deletions

View file

@ -10,7 +10,7 @@ publish :
test:
pytest -v
flake8
vermin toot
vermin witchie
coverage:
coverage erase
@ -20,7 +20,7 @@ coverage:
clean :
find . -name "*pyc" | xargs rm -rf $1
rm -rf build dist MANIFEST htmlcov toot*.tar.gz
rm -rf build dist MANIFEST htmlcov witchie*.tar.gz
changelog:
./scripts/generate_changelog > CHANGELOG.md
@ -33,4 +33,4 @@ docs-serve:
mdbook serve
docs-deploy: docs
rsync --archive --compress --delete --stats book/ bezdomni:web/toot
rsync --archive --compress --delete --stats book/ bezdomni:web/witchie

View file

@ -1,27 +1,16 @@
============================
Toot - a Mastodon CLI client
Witchie - an Akkoma CLI client
============================
.. image:: https://raw.githubusercontent.com/ihabunek/toot/master/trumpet.png
Toot is a CLI and TUI tool for interacting with Mastodon instances from the command line.
.. image:: https://img.shields.io/badge/author-%40ihabunek-blue.svg?maxAge=3600&style=flat-square
:target: https://mastodon.social/@ihabunek
.. image:: https://img.shields.io/github/license/ihabunek/toot.svg?maxAge=3600&style=flat-square
:target: https://opensource.org/licenses/GPL-3.0
.. image:: https://img.shields.io/pypi/v/toot.svg?maxAge=3600&style=flat-square
:target: https://pypi.python.org/pypi/toot
Witchie is a CLI and TUI tool for interacting with Akkoma instances from the command line.
It is a fork of [ibuhanek's toot](https://github.com/ihabunek/toot) for Mastodon.
Resources
---------
* Homepage: https://github.com/ihabunek/toot
* Issues: https://github.com/ihabunek/toot/issues
* Documentation: https://toot.bezdomni.net/
* Mailing list for discussion, support and patches:
https://lists.sr.ht/~ihabunek/toot-discuss
* Informal discussion: #toot IRC channel on `libera.chat <https://libera.chat/>`_
* Homepage: https://sr.ht/~huyngo/witchie
* Mailing list for discussion: https://lists.sr.ht/~huyngo/witchie
* Bugs/feature requests: https://todo.sr.ht/~huyngo/witchie
Features
--------
@ -30,12 +19,12 @@ Features
* Support for media uploads, spoiler text, sensitive content
* Search by account or hash tag
* Following, muting and blocking accounts
* Simple switching between authenticated in Mastodon accounts
* Simple switching between authenticated accounts
Terminal User Interface
-----------------------
toot includes a terminal user interface (TUI). Run it with ``toot tui``.
witchie includes a terminal user interface (TUI). Run it with ``witchie tui``.
.. image :: https://raw.githubusercontent.com/ihabunek/toot/master/docs/images/tui_list.png
@ -45,6 +34,7 @@ toot includes a terminal user interface (TUI). Run it with ``toot tui``.
License
-------
Copyright Ivan Habunek <ivan@habunek.com> and contributors.
Copyright 2017-2023 Ivan Habunek <ivan@habunek.com> and contributors.
Copyright 2023 Ngô Ngọc Đức Huy <huyngo@disroot.org>
Licensed under `GPLv3 <http://www.gnu.org/licenses/gpl-3.0.html>`_, see `LICENSE <LICENSE>`_.

View file

@ -3,7 +3,7 @@
from setuptools import setup
long_description = """
Toot is a CLI and TUI tool for interacting with Mastodon instances from the
Witchie is a CLI and TUI tool for interacting with Akkoma instances from the
command line.
Allows posting text and media to the timeline, searching, following, muting
@ -11,18 +11,18 @@ and blocking accounts and other actions.
"""
setup(
name='toot',
name='witchie',
version='0.39.0',
description='Mastodon CLI client',
description='Akkoma CLI client',
long_description=long_description.strip(),
author='Ivan Habunek',
author_email='ivan@habunek.com',
url='https://github.com/ihabunek/toot/',
author='Ngô Ngọc Đức Huy',
author_email='huyngo@disroot.org',
url='https://git.sr.ht/~huyngo/witchie/',
project_urls={
'Documentation': 'https://toot.bezdomni.net/',
'Issue tracker': 'https://github.com/ihabunek/toot/issues/',
'Issue tracker': 'https://todo.sr.ht/~huyngo/witchie/',
},
keywords='mastodon toot',
keywords='akkoma',
license='GPLv3',
classifiers=[
'Development Status :: 4 - Beta',
@ -31,7 +31,7 @@ setup(
'License :: OSI Approved :: GNU General Public License v3 (GPLv3)',
'Programming Language :: Python :: 3',
],
packages=['toot', 'toot.tui', 'toot.tui.richtext', 'toot.utils'],
packages=['akkoma', 'akkoma.tui', 'akkoma.tui.richtext', 'akkoma.utils'],
python_requires=">=3.7",
install_requires=[
"requests>=2.13,<3.0",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View file

@ -11,24 +11,24 @@ User = namedtuple('User', ['instance', 'username', 'access_token'])
DEFAULT_INSTANCE = 'https://mastodon.social'
CLIENT_NAME = 'toot - a Mastodon CLI client'
CLIENT_WEBSITE = 'https://github.com/ihabunek/toot'
CLIENT_NAME = 'witchie - an Akkoma CLI client'
CLIENT_WEBSITE = 'https://sr.ht/~huyngo/witchie'
TOOT_CONFIG_DIR_NAME = "toot"
CONFIG_DIR_NAME = "witchie"
def get_config_dir():
"""Returns the path to toot config directory"""
"""Returns the path to witchie config directory"""
# On Windows, store the config in roaming appdata
if sys.platform == "win32" and "APPDATA" in os.environ:
return join(os.getenv("APPDATA"), TOOT_CONFIG_DIR_NAME)
return join(os.getenv("APPDATA"), CONFIG_DIR_NAME)
# Respect XDG_CONFIG_HOME env variable if set
# https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
if "XDG_CONFIG_HOME" in os.environ:
config_home = expanduser(os.environ["XDG_CONFIG_HOME"])
return join(config_home, TOOT_CONFIG_DIR_NAME)
return join(config_home, CONFIG_DIR_NAME)
# Default to ~/.config/toot/
return join(expanduser("~"), ".config", TOOT_CONFIG_DIR_NAME)
# Default to ~/.config/witchie/
return join(expanduser("~"), ".config", CONFIG_DIR_NAME)

View file

@ -7,9 +7,9 @@ from requests import Response
from typing import BinaryIO, List, Optional
from urllib.parse import urlparse, urlencode, quote
from toot import App, User, http, CLIENT_NAME, CLIENT_WEBSITE
from toot.exceptions import AuthenticationError, ConsoleError
from toot.utils import drop_empty_values, str_bool, str_bool_nullable
from witchie import App, User, http, CLIENT_NAME, CLIENT_WEBSITE
from witchie.exceptions import AuthenticationError, ConsoleError
from witchie.utils import drop_empty_values, str_bool, str_bool_nullable
SCOPES = 'read write follow'
@ -255,7 +255,7 @@ def scheduled_statuses(app, user):
def delete_status(app, user, status_id):
"""
Deletes a status with given ID.
https://github.com/tootsuite/documentation/blob/master/Using-the-API/API.md#deleting-a-status
https://docs.joinmastodon.org/methods/statuses/#delete
"""
return http.delete(app, user, f"/api/v1/statuses/{status_id}")

View file

@ -4,9 +4,9 @@ import webbrowser
from builtins import input
from getpass import getpass
from toot import api, config, DEFAULT_INSTANCE, User, App
from toot.exceptions import ApiError, ConsoleError
from toot.output import print_out
from witchie import api, config, DEFAULT_INSTANCE, User, App
from witchie.exceptions import ApiError, ConsoleError
from witchie.output import print_out
from urllib.parse import urlparse
@ -104,8 +104,8 @@ def login_interactive(app, email=None):
BROWSER_LOGIN_EXPLANATION = """
This authentication method requires you to log into your Mastodon instance
in your browser, where you will be asked to authorize <yellow>toot</yellow> to access
This authentication method requires you to log into your Akkoma instance
in your browser, where you will be asked to authorize <yellow>witchie</yellow> to access
your account. When you do, you will be given an <yellow>authorization code</yellow>
which you need to paste here.
"""

View file

@ -6,15 +6,15 @@ import platform
from datetime import datetime, timedelta, timezone
from time import sleep, time
from toot import api, config, __version__
from toot.auth import login_interactive, login_browser_interactive, create_app_interactive
from toot.entities import Account, Instance, Notification, Status, from_dict
from toot.exceptions import ApiError, ConsoleError
from toot.output import (print_lists, print_out, print_instance, print_account, print_acct_list,
from witchie import api, config, __version__
from witchie.auth import login_interactive, login_browser_interactive, create_app_interactive
from witchie.entities import Account, Instance, Notification, Status, from_dict
from witchie.exceptions import ApiError, ConsoleError
from witchie.output import (print_lists, print_out, print_instance, print_account, print_acct_list,
print_search_results, print_status, print_table, print_timeline, print_notifications,
print_tag_list, print_list_accounts, print_user_list)
from toot.utils import args_get_instance, delete_tmp_status_file, editor_input, multiline_input, EOF_KEY
from toot.utils.datetime import parse_datetime
from witchie.utils import args_get_instance, delete_tmp_status_file, editor_input, multiline_input, EOF_KEY
from witchie.utils.datetime import parse_datetime
def get_timeline_generator(app, user, args):
@ -85,10 +85,10 @@ def thread(app, user, args):
if args.json:
print(context_response.text)
else:
toot = api.fetch_status(app, user, args.status_id).json()
post = api.fetch_status(app, user, args.status_id).json()
context = context_response.json()
statuses = chain(context["ancestors"], [toot], context["descendants"])
statuses = chain(context["ancestors"], [post], context["descendants"])
print_timeline(from_dict(Status, s) for s in statuses)
@ -129,9 +129,9 @@ def post(app, user, args):
if "scheduled_at" in status:
scheduled_at = parse_datetime(status["scheduled_at"])
scheduled_at = datetime.strftime(scheduled_at, "%Y-%m-%d %H:%M:%S%z")
print_out(f"Toot scheduled for: <green>{scheduled_at}</green>")
print_out(f"Post scheduled for: <green>{scheduled_at}</green>")
else:
print_out(f"Toot posted: <green>{status['url']}")
print_out(f"Post posted: <green>{status['url']}")
delete_tmp_status_file()
@ -146,7 +146,7 @@ def _get_status_text(text, editor, media):
if editor:
text = editor_input(editor, text)
elif not text and not media:
print_out("Write or paste your toot. Press <yellow>{}</yellow> to post it.".format(EOF_KEY))
print_out("Write or paste your post. Press <yellow>{}</yellow> to post it.".format(EOF_KEY))
text = multiline_input()
return text
@ -318,7 +318,7 @@ def auth(app, user, args):
def env(app, user, args):
print_out(f"toot {__version__}")
print_out(f"witchie {__version__}")
print_out(f"Python {sys.version}")
print_out(platform.platform())

View file

@ -4,17 +4,17 @@ import os
from functools import wraps
from os.path import dirname, join
from toot import User, App, get_config_dir
from toot.exceptions import ConsoleError
from toot.output import print_out
from witchie import User, App, get_config_dir
from witchie.exceptions import ConsoleError
from witchie.output import print_out
TOOT_CONFIG_FILE_NAME = "config.json"
WITCHIE_CONFIG_FILE_NAME = "config.json"
def get_config_file_path():
"""Returns the path to toot config file."""
return join(get_config_dir(), TOOT_CONFIG_FILE_NAME)
"""Returns the path to witchie config file."""
return join(get_config_dir(), WITCHIE_CONFIG_FILE_NAME)
def user_id(user):
@ -22,7 +22,7 @@ def user_id(user):
def make_config(path):
"""Creates an empty toot configuration file."""
"""Creates an empty witchie configuration file."""
config = {
"apps": {},
"users": {},

View file

@ -7,10 +7,10 @@ import sys
from argparse import ArgumentParser, FileType, ArgumentTypeError, Action
from collections import namedtuple
from itertools import chain
from toot import config, commands, CLIENT_NAME, CLIENT_WEBSITE, __version__, settings
from toot.exceptions import ApiError, ConsoleError
from toot.output import print_out, print_err
from toot.settings import get_setting
from witchie import config, commands, CLIENT_NAME, CLIENT_WEBSITE, __version__, settings
from witchie.exceptions import ApiError, ConsoleError
from witchie.output import print_out, print_err
from witchie.settings import get_setting
VISIBILITY_CHOICES = ["public", "unlisted", "private", "direct"]
VISIBILITY_CHOICES_STR = ", ".join(f"'{v}'" for v in VISIBILITY_CHOICES)
@ -62,7 +62,7 @@ class BooleanOptionalAction(Action):
def get_default_visibility():
return os.getenv("TOOT_POST_VISIBILITY", "public")
return os.getenv("WITCHIE_POST_VISIBILITY", "public")
def language(value):
@ -94,8 +94,8 @@ def privacy(value):
def timeline_count(value):
n = int(value)
if not 0 < n <= 20:
raise ArgumentTypeError("Number of toots should be between 1 and 20.")
if not 0 < n <= 40:
raise ArgumentTypeError("Number of posts should be between 1 and 40.")
return n
@ -225,7 +225,7 @@ visibility_arg = (["-v", "--visibility"], {
"default": get_default_visibility(),
"help": f"Post visibility. One of: {VISIBILITY_CHOICES_STR}. Defaults to "
f"'{get_default_visibility()}' which can be overridden by setting "
"the TOOT_POST_VISIBILITY environment variable",
"the WITCHIE_POST_VISIBILITY environment variable",
})
tag_arg = (["tag_name"], {
@ -239,7 +239,7 @@ json_arg = (["--json"], {
"help": "print json instead of plaintext",
})
# Arguments for selecting a timeline (see `toot.commands.get_timeline_generator`)
# Arguments for selecting a timeline (see `witchie.commands.get_timeline_generator`)
common_timeline_args = [
(["-p", "--public"], {
"action": "store_true",
@ -272,7 +272,7 @@ common_timeline_args = [
timeline_and_bookmark_args = [
(["-c", "--count"], {
"type": timeline_count,
"help": "number of toots to show per page (1-20, default 10).",
"help": "number of posts to show per page (1-40, default 10).",
"default": 10,
}),
(["-r", "--reverse"], {
@ -283,7 +283,7 @@ timeline_and_bookmark_args = [
(["-1", "--once"], {
"action": "store_true",
"default": False,
"help": "Only show the first <count> toots, do not prompt to continue.",
"help": "Only show the first <count> posts, do not prompt to continue.",
}),
]
@ -379,7 +379,7 @@ AUTH_COMMANDS = [
TUI_COMMANDS = [
Command(
name="tui",
description="Launches the toot terminal user interface",
description="Launches the post terminal user interface",
arguments=[
(["--relative-datetimes"], {
"action": "store_true",
@ -463,10 +463,10 @@ READ_COMMANDS = [
),
Command(
name="thread",
description="Show toot thread items",
description="Show post thread items",
arguments=[
(["status_id"], {
"help": "Show thread for toot.",
"help": "Show thread for post.",
}),
json_arg,
],
@ -540,13 +540,13 @@ POST_COMMANDS = [
}),
(["-l", "--language"], {
"type": language,
"help": "ISO 639-1 language code of the toot, to skip automatic detection",
"help": "ISO 639-1 language code of the post, to skip automatic detection",
}),
(["-e", "--editor"], {
"type": editor,
"nargs": "?",
"const": os.getenv("EDITOR", ""), # option given without value
"help": "Specify an editor to compose your toot, "
"help": "Specify an editor to compose your post, "
"defaults to editor defined in $EDITOR env variable.",
}),
(["--scheduled-at"], {
@ -556,7 +556,7 @@ POST_COMMANDS = [
}),
(["--scheduled-in"], {
"type": duration,
"help": f"""Schedule the toot to be posted after a given amount
"help": f"""Schedule the post to be posted after a given amount
of time, {DURATION_EXAMPLES}. Must be at least 5
minutes.""",
}),
@ -876,18 +876,18 @@ def print_usage():
for cmd in cmds:
cmd_name = cmd.name.ljust(max_name_len + 2)
print_out(" <yellow>toot {}</yellow> {}".format(cmd_name, cmd.description))
print_out(" <yellow>witchie {}</yellow> {}".format(cmd_name, cmd.description))
print_out("")
print_out("To get help for each command run:")
print_out(" <yellow>toot \\<command> --help</yellow>")
print_out(" <yellow>witchie \\<command> --help</yellow>")
print_out("")
print_out("<green>{}</green>".format(CLIENT_WEBSITE))
def get_argument_parser(name, command):
parser = ArgumentParser(
prog='toot %s' % name,
prog='witchie %s' % name,
description=command.description,
epilog=CLIENT_WEBSITE)
@ -918,7 +918,7 @@ def run_command(app, user, name, args):
if not command:
print_err(f"Unknown command '{name}'")
print_out("Run <yellow>toot --help</yellow> to show a list of available commands.")
print_out("Run <yellow>witchie --help</yellow> to show a list of available commands.")
return
parser = get_argument_parser(name, command)
@ -932,7 +932,7 @@ def run_command(app, user, name, args):
if command.require_auth and (not user or not app):
print_err("This command requires that you are logged in.")
print_err("Please run `toot login` first.")
print_err("Please run `witchie login` first.")
return
fn = commands.__dict__.get(name)

View file

@ -1,7 +1,7 @@
"""
Dataclasses which represent entities returned by the Mastodon API.
Data classes my have an optional static method named `__toot_prepare__` which is
Data classes my have an optional static method named `__post_prepare__` which is
used when constructing the data class using `from_dict`. The method will be
called with the dict and may modify it and return a modified dict. This is used
to implement any pre-processing which may be required, e.g. to support
@ -16,9 +16,9 @@ from functools import lru_cache
from typing import Any, Dict, List, Optional, Tuple, Type, TypeVar, Union
from typing import get_type_hints
from toot.typing_compat import get_args, get_origin
from toot.utils import get_text
from toot.utils.datetime import parse_datetime
from witchie.typing_compat import get_args, get_origin
from witchie.utils import get_text
from witchie.utils.datetime import parse_datetime
@dataclass
@ -76,7 +76,7 @@ class Account:
source: Optional[dict]
@staticmethod
def __toot_prepare__(obj: Dict) -> Dict:
def __post_prepare__(obj: Dict) -> Dict:
# Pleroma has not yet converted last_status_at from datetime to date
# so trim it here so it doesn't break when converting to date.
# See: https://git.pleroma.social/pleroma/pleroma/-/issues/1470
@ -266,7 +266,8 @@ class Status:
return self.reblog or self
@staticmethod
def __toot_prepare__(obj: Dict) -> Dict:
def __post_prepare__(obj: Dict) -> Dict:
# TODO: check this
# Pleroma has a bug where created_at is set to an empty string.
# To avoid marking created_at as optional, which would require work
# because we count on it always existing, set it to current datetime.
@ -430,8 +431,8 @@ class ConversionError(Exception):
def from_dict(cls: Type[T], data: Dict) -> T:
"""Convert a nested dict into an instance of `cls`."""
# Apply __toot_prepare__ if it exists
prepare = getattr(cls, '__toot_prepare__', None)
# Apply __post_prepare__ if it exists
prepare = getattr(cls, '__post_prepare__', None)
if prepare:
data = prepare(data)

View file

@ -1,15 +1,15 @@
from requests import Request, Session
from requests.exceptions import RequestException
from toot import __version__
from toot.exceptions import NotFoundError, ApiError
from toot.logging import log_request, log_request_exception, log_response
from witchie import __version__
from witchie.exceptions import NotFoundError, ApiError
from witchie.logging import log_request, log_request_exception, log_response
def send_request(request, allow_redirects=True):
# Set a user agent string
# Required for accessing instances using Cloudfront DDOS protection.
request.headers["User-Agent"] = "toot/{}".format(__version__)
request.headers["User-Agent"] = "witchie/{}".format(__version__)
log_request(request)

View file

@ -5,7 +5,7 @@ from logging import getLogger
from requests import Request, RequestException, Response
from urllib.parse import urlencode
logger = getLogger("toot")
logger = getLogger("witchie")
VERBOSE = "--verbose" in sys.argv

View file

@ -4,10 +4,10 @@ import sys
import textwrap
from functools import lru_cache
from toot import settings
from toot.utils import get_text, html_to_paragraphs
from toot.entities import Account, Instance, Notification, Poll, Status
from toot.wcstring import wc_wrap
from witchie import settings
from witchie.utils import get_text, html_to_paragraphs
from witchie.entities import Account, Instance, Notification, Poll, Status
from witchie.wcstring import wc_wrap
from typing import Iterable, List
from wcwidth import wcswidth

View file

@ -4,17 +4,17 @@ import sys
from functools import lru_cache
from os.path import exists, join
from tomlkit import parse
from toot import get_config_dir
from witchie import get_config_dir
from typing import Optional, Type, TypeVar
DISABLE_SETTINGS = False
TOOT_SETTINGS_FILE_NAME = "settings.toml"
WITCHIE_SETTINGS_FILE_NAME = "settings.toml"
def get_settings_path():
return join(get_config_dir(), TOOT_SETTINGS_FILE_NAME)
return join(get_config_dir(), WITCHIE_SETTINGS_FILE_NAME)
def load_settings() -> dict:
@ -72,7 +72,7 @@ def get_debug() -> bool:
def get_debug_file() -> Optional[str]:
from_env = os.getenv("TOOT_LOG_FILE")
from_env = os.getenv("WITCHIE_LOG_FILE")
if from_env:
return from_env

View file

@ -4,9 +4,9 @@ import urwid
from concurrent.futures import ThreadPoolExecutor
from toot import api, config, __version__, settings
from toot.console import get_default_visibility
from toot.exceptions import ApiError
from witchie import api, config, __version__, settings
from witchie.console import get_default_visibility
from witchie.exceptions import ApiError
from .compose import StatusComposer
from .constants import PALETTE
@ -15,14 +15,14 @@ from .overlays import ExceptionStackTrace, GotoMenu, Help, StatusSource, StatusL
from .overlays import StatusDeleteConfirmation, Account
from .poll import Poll
from .timeline import Timeline
from .utils import get_max_toot_chars, parse_content_links, copy_to_clipboard
from .utils import get_max_post_chars, parse_content_links, copy_to_clipboard
logger = logging.getLogger(__name__)
urwid.set_encoding('UTF-8')
DEFAULT_MAX_TOOT_CHARS = 500
DEFAULT_MAX_POST_CHARS = 500
class Header(urwid.WidgetWrap):
@ -32,7 +32,7 @@ class Header(urwid.WidgetWrap):
self.text = urwid.Text("")
self.cols = urwid.Columns([
("pack", urwid.Text(('header_bold', 'toot'))),
("pack", urwid.Text(('header_bold', 'post'))),
("pack", urwid.Text(('header', ' | {}@{}'.format(user.username, app.instance)))),
("pack", self.text),
])
@ -124,14 +124,14 @@ class TUI(urwid.Frame):
self.executor = ThreadPoolExecutor(max_workers=1)
self.timeline_generator = api.home_timeline_generator(app, user, limit=40)
# Show intro screen while toots are being loaded
# Show intro screen while posts are being loaded
self.body = self.build_intro()
self.header = Header(app, user)
self.footer = Footer()
self.footer.set_status("Loading...")
# Default max status length, updated on startup
self.max_toot_chars = DEFAULT_MAX_TOOT_CHARS
self.max_post_chars = DEFAULT_MAX_POST_CHARS
self.timeline = None
self.overlay = None
@ -157,7 +157,7 @@ class TUI(urwid.Frame):
# NB: Padding with width="clip" will convert the fixed BigText widget
# to a flow widget so it can be used in a Pile.
big_text = "Toot {}".format(__version__)
big_text = "Witchie {}".format(__version__)
big_text = urwid.BigText(("intro_bigtext", big_text), font)
big_text = urwid.Padding(big_text, align="center", width="clip")
@ -170,7 +170,7 @@ class TUI(urwid.Frame):
" and contributors"
], align="center"),
urwid.Divider(),
urwid.Text(("intro_smalltext", "Loading toots..."), align="center"),
urwid.Text(("intro_smalltext", "Loading posts..."), align="center"),
])
return urwid.Filler(intro)
@ -296,7 +296,7 @@ class TUI(urwid.Frame):
def async_load_instance(self):
"""
Attempt to update max_toot_chars from instance data.
Attempt to update max_post_chars from instance data.
Does not work on vanilla Mastodon, works on Pleroma.
See: https://github.com/tootsuite/mastodon/issues/4915
@ -309,8 +309,8 @@ class TUI(urwid.Frame):
return api.get_instance(self.app.base_url).json()
def _done(instance):
self.max_toot_chars = get_max_toot_chars(instance, DEFAULT_MAX_TOOT_CHARS)
logger.info(f"Max toot chars set to: {self.max_toot_chars}")
self.max_post_chars = get_max_post_chars(instance, DEFAULT_MAX_POST_CHARS)
logger.info(f"Max post chars set to: {self.max_post_chars}")
if "translation" in instance:
# instance is advertising translation service
@ -400,7 +400,7 @@ class TUI(urwid.Frame):
def _post(timeline, *args):
self.post_status(*args)
composer = StatusComposer(self.max_toot_chars, self.user.username, in_reply_to)
composer = StatusComposer(self.max_post_chars, self.user.username, in_reply_to)
urwid.connect_signal(composer, "close", _close)
urwid.connect_signal(composer, "post", _post)
self.open_overlay(composer, title="Compose status")

View file

@ -1,7 +1,7 @@
import urwid
import logging
from toot.console import get_default_visibility
from witchie.console import get_default_visibility
from .constants import VISIBILITY_OPTIONS
from .widgets import Button, EditBox

View file

@ -1,6 +1,6 @@
from collections import namedtuple
from toot.utils.datetime import parse_datetime
from witchie.utils.datetime import parse_datetime
Author = namedtuple("Author", ["account", "display_name", "username"])

View file

@ -3,11 +3,11 @@ import traceback
import urwid
import webbrowser
from toot import __version__
from toot import api
from toot.tui.utils import highlight_keys
from toot.tui.widgets import Button, EditBox, SelectableText
from toot.tui.richtext import html_to_widgets
from witchie import __version__
from witchie import api
from witchie.tui.utils import highlight_keys
from witchie.tui.widgets import Button, EditBox, SelectableText
from witchie.tui.richtext import html_to_widgets
class StatusSource(urwid.Padding):
@ -198,7 +198,7 @@ class Help(urwid.Padding):
def h(text):
return highlight_keys(text, "shortcut")
yield urwid.Text(("bold", "toot {}".format(__version__)))
yield urwid.Text(("bold", "witchie {}".format(__version__)))
yield urwid.Divider()
yield urwid.Text(("bold", "General usage"))
yield urwid.Divider()
@ -209,7 +209,7 @@ class Help(urwid.Padding):
yield urwid.Divider()
yield urwid.Text(("bold", "General keys"))
yield urwid.Divider()
yield urwid.Text(h(" [Q] - quit toot"))
yield urwid.Text(h(" [Q] - quit witchie"))
yield urwid.Text(h(" [G] - go to - switch timelines"))
yield urwid.Text(h(" [E] - save/unsave (pin) current timeline"))
yield urwid.Text(h(" [,] - refresh current timeline"))
@ -236,7 +236,7 @@ class Help(urwid.Padding):
yield urwid.Text(("bold", "Links"))
yield urwid.Divider()
yield link("Documentation: ", "https://toot.bezdomni.net/")
yield link("Project home: ", "https://github.com/ihabunek/toot/")
yield link("Project home: ", "https://sr.ht/~huyngo/witchie")
class Account(urwid.ListBox):

View file

@ -1,8 +1,8 @@
import urwid
from toot import api
from toot.exceptions import ApiError
from toot.utils.datetime import parse_datetime
from witchie import api
from witchie.exceptions import ApiError
from witchie.utils.datetime import parse_datetime
from .widgets import Button, CheckBox, RadioButton
from .richtext import html_to_widgets

View file

@ -1,7 +1,7 @@
import urwid
from toot.tui.utils import highlight_hashtags
from toot.utils import format_content
from witchie.tui.utils import highlight_hashtags
from witchie.utils import format_content
from typing import List
try:

View file

@ -3,8 +3,8 @@ import urwid
import unicodedata
from bs4.element import NavigableString, Tag
from toot.tui.constants import PALETTE
from toot.utils import parse_html, urlencode_url
from witchie.tui.constants import PALETTE
from witchie.utils import parse_html, urlencode_url
from typing import List, Tuple
from urwid.util import decompose_tagmarkup
from urwidgets import Hyperlink, TextEmbed

View file

@ -4,17 +4,17 @@ import webbrowser
from typing import List, Optional
from toot.tui import app
from toot.tui.richtext import html_to_widgets, url_to_widget
from toot.utils.datetime import parse_datetime, time_ago
from toot.utils.language import language_name
from witchie.tui import app
from witchie.tui.richtext import html_to_widgets, url_to_widget
from witchie.utils.datetime import parse_datetime, time_ago
from witchie.utils.language import language_name
from toot.entities import Status
from toot.tui.scroll import Scrollable, ScrollBar
from toot.tui.utils import highlight_keys
from toot.tui.widgets import SelectableText, SelectableColumns
from witchie.entities import Status
from witchie.tui.scroll import Scrollable, ScrollBar
from witchie.tui.utils import highlight_keys
from witchie.tui.widgets import SelectableText, SelectableColumns
logger = logging.getLogger("toot")
logger = logging.getLogger("witchie")
class Timeline(urwid.Columns):

View file

@ -88,17 +88,17 @@ def copy_to_clipboard(screen: urwid.raw_display.Screen, text: str):
screen.flush()
def get_max_toot_chars(instance, default=500):
def get_max_post_chars(instance, default=500):
# Mastodon
# https://docs.joinmastodon.org/entities/Instance/#max_characters
max_toot_chars = deep_get(instance, ["configuration", "statuses", "max_characters"])
if isinstance(max_toot_chars, int):
return max_toot_chars
max_post_chars = deep_get(instance, ["configuration", "statuses", "max_characters"])
if isinstance(max_post_chars, int):
return max_post_chars
# Pleroma
max_toot_chars = instance.get("max_toot_chars")
if isinstance(max_toot_chars, int):
return max_toot_chars
max_post_chars = instance.get("max_post_chars")
if isinstance(max_post_chars, int):
return max_post_chars
return default

View file

@ -9,7 +9,7 @@ import warnings
from bs4 import BeautifulSoup
from typing import Dict
from toot.exceptions import ConsoleError
from witchie.exceptions import ConsoleError
from urllib.parse import urlparse, urlencode, quote, unquote
@ -104,7 +104,7 @@ EDITOR_DIVIDER = "------------------------ >8 ------------------------"
EDITOR_INPUT_INSTRUCTIONS = f"""
{EDITOR_DIVIDER}
Do not modify or remove the line above.
Enter your toot above it.
Enter your post above it.
Everything below it will be ignored.
"""
@ -145,11 +145,11 @@ def delete_tmp_status_file():
def _tmp_status_path() -> str:
tmp_dir = tempfile.gettempdir()
return f"{tmp_dir}/.status.toot"
return f"{tmp_dir}/.status.post"
def _use_existing_tmp_file(tmp_path) -> bool:
from toot.output import print_out
from witchie.output import print_out
if os.path.exists(tmp_path):
print_out(f"<cyan>Found a draft status at: {tmp_path}</cyan>")
@ -179,15 +179,15 @@ def args_get_instance(instance, scheme, default=None):
def _warn_scheme_deprecated():
from toot.output import print_err
from witchie.output import print_err
print_err("\n".join([
"--disable-https flag is deprecated and will be removed.",
"Please specify the instance as URL instead.",
"e.g. instead of writing:",
" toot instance unsafehost.com --disable-https",
" witchie instance unsafehost.com --disable-https",
"instead write:",
" toot instance http://unsafehost.com\n"
" witchie instance http://unsafehost.com\n"
]))