+15
.tangled/workflows/run-tests.yml
+15
.tangled/workflows/run-tests.yml
+8
-3
README.md
+8
-3
README.md
···-XPost is a social media cross-posting tool that differs from others by using streaming APIs to allow instant, zero-input cross-posting. this means you can continue posting on your preferred platform without using special apps.-XPost tries to support as many features as possible. for example, when cross-posting from mastodon to bluesky, unsupported file types will be attached as links. posts with mixed media or too many files will be split and spread across text.
···+> this is the dev branch for xpost next, a full rewrite of xpost. the older version is available on the master branch.+> planned work for this branch can be found and tracked here: https://tangled.org/@zenfyr.dev/xpost/issues/1+xpost is a social media cross-posting tool that differs from others by using streaming APIs to allow instant, zero-input cross-posting. this means you can continue posting on your preferred platform without using special apps.+xpost tries to support as many features as possible. for example, when cross-posting from mastodon to bluesky, unsupported file types will be attached as links. posts with mixed media or too many files will be split and spread across text.
+164
atproto/identity.py
+164
atproto/identity.py
···
···
+11
atproto/util.py
+11
atproto/util.py
···
···
+50
bluesky/info.py
+50
bluesky/info.py
···
···
+283
bluesky/input.py
+283
bluesky/input.py
···
···
+95
bluesky/tokens.py
+95
bluesky/tokens.py
···
···
+23
-8
cross/attachments.py
+23
-8
cross/attachments.py
···
···
-18
cross/fragments.py
-18
cross/fragments.py
···
···
+170
cross/media.py
+170
cross/media.py
···
···+def download_blob(url: str, alt: str | None = None, max_bytes: int = 100_000_000) -> Blob | None:
+14
-8
cross/post.py
+14
-8
cross/post.py
······
······
+140
-10
cross/service.py
+140
-10
cross/service.py
···
···
+23
cross/tokens.py
+23
cross/tokens.py
···
···
+20
-2
database/connection.py
+20
-2
database/connection.py
···
+13
-27
database/migrations.py
+13
-27
database/migrations.py
·········
······+def apply_migration(self, version: int, filename: str, migration: Callable[[sqlite3.Connection], None]):···
+11
-2
env.py
+11
-2
env.py
···
+40
-18
main.py
+40
-18
main.py
······
······
+109
mastodon/info.py
+109
mastodon/info.py
···
···
+232
mastodon/input.py
+232
mastodon/input.py
···
···
+178
mastodon/output.py
+178
mastodon/output.py
···
···
+31
mastodon/parser.py
+31
mastodon/parser.py
···
···
-13
migrations/001_initdb.sql
-13
migrations/001_initdb.sql
···
···
+21
migrations/001_initdb_v1.py
+21
migrations/001_initdb_v1.py
···
···
-2
migrations/002_add_reposted_column.sql
-2
migrations/002_add_reposted_column.sql
+11
migrations/002_add_reposted_column_v1.py
+11
migrations/002_add_reposted_column_v1.py
···
···
-2
migrations/003_add_extra_data.sql
-2
migrations/003_add_extra_data.sql
+22
migrations/003_add_extra_data_column_v1.py
+22
migrations/003_add_extra_data_column_v1.py
···
···+data = conn.execute("SELECT id, identifier FROM posts WHERE service = 'https://bsky.app';").fetchall()+_ = conn.executemany("UPDATE posts SET identifier = ?, extra_data = ? WHERE id = ?;", rewrites)
+52
migrations/004_initdb_next.py
+52
migrations/004_initdb_next.py
···
···
+12
migrations/005_add_indexes.py
+12
migrations/005_add_indexes.py
···
···
+35
migrations/_registry.py
+35
migrations/_registry.py
···
···
+22
misskey/info.py
+22
misskey/info.py
···
···
+227
misskey/input.py
+227
misskey/input.py
···
···+streaming: str = f"{'wss' if self.url.startswith('https') else 'ws'}://{self.url.split('://', 1)[1]}"
+10
pyproject.toml
+10
pyproject.toml
···
+32
registry.py
+32
registry.py
···
···
+33
registry_bootstrap.py
+33
registry_bootstrap.py
···
···
+61
tests/util/util_test.py
+61
tests/util/util_test.py
···
···
+49
util/cache.py
+49
util/cache.py
···
···
+29
util/dummy.py
+29
util/dummy.py
···
···
+150
util/html.py
+150
util/html.py
···
···
+126
util/markdown.py
+126
util/markdown.py
···
···
+120
util/splitter.py
+120
util/splitter.py
···
···
+30
-1
util/util.py
+30
-1
util/util.py
···
+88
uv.lock
+88
uv.lock
·········
···+sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }+{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },+sdist = { url = "https://files.pythonhosted.org/packages/8c/8b/57666417c0f90f08bcafa776861060426765fdb422eb10212086fb811d26/dnspython-2.8.0.tar.gz", hash = "sha256:181d3c6996452cb1189c4046c61599b84a5a86e099562ffde77d26984ff26d0f", size = 368251, upload-time = "2025-09-07T18:58:00.022Z" }+{ url = "https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl", hash = "sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af", size = 331094, upload-time = "2025-09-07T18:57:58.071Z" },+sdist = { url = "https://files.pythonhosted.org/packages/ce/e7/bbaab0d2a33e07c8278910c1d0d8d4f3781293dfbc70b5c38197159046bf/grapheme-0.6.0.tar.gz", hash = "sha256:44c2b9f21bbe77cfb05835fec230bd435954275267fea1858013b102f8603cca", size = 207306, upload-time = "2020-03-07T17:13:55.492Z" }···+sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" }+{ url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },+sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" }+{ url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" },+sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }+{ url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },+sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" }+{ url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" },+sdist = { url = "https://files.pythonhosted.org/packages/a3/5c/00a0e072241553e1a7496d638deababa67c5058571567b92a7eaa258397c/pytest-8.4.2.tar.gz", hash = "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01", size = 1519618, upload-time = "2025-09-04T14:34:22.711Z" }+{ url = "https://files.pythonhosted.org/packages/a8/a4/20da314d277121d6534b3a980b29035dcd51e6744bd79075a6ce8fa4eb8d/pytest-8.4.2-py3-none-any.whl", hash = "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79", size = 365750, upload-time = "2025-09-04T14:34:20.226Z" },···