socialchimp 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. socialchimp-0.1.0/.github/workflows/ci.yml +44 -0
  2. socialchimp-0.1.0/.github/workflows/publish.yml +80 -0
  3. socialchimp-0.1.0/.gitignore +27 -0
  4. socialchimp-0.1.0/.pre-commit-config.yaml +49 -0
  5. socialchimp-0.1.0/CHANGELOG.md +67 -0
  6. socialchimp-0.1.0/CONTRIBUTING.md +76 -0
  7. socialchimp-0.1.0/LICENSE +21 -0
  8. socialchimp-0.1.0/PKG-INFO +159 -0
  9. socialchimp-0.1.0/README.md +118 -0
  10. socialchimp-0.1.0/docs/PLAN.md +187 -0
  11. socialchimp-0.1.0/docs/adding-a-platform.md +306 -0
  12. socialchimp-0.1.0/docs/frameworks.md +350 -0
  13. socialchimp-0.1.0/docs/getting-started.md +304 -0
  14. socialchimp-0.1.0/docs/platforms.md +268 -0
  15. socialchimp-0.1.0/docs/releasing.md +99 -0
  16. socialchimp-0.1.0/examples/README.md +7 -0
  17. socialchimp-0.1.0/examples/post_to_many.py +75 -0
  18. socialchimp-0.1.0/examples/post_to_mastodon.py +96 -0
  19. socialchimp-0.1.0/pyproject.toml +196 -0
  20. socialchimp-0.1.0/src/socialchimp/__init__.py +135 -0
  21. socialchimp-0.1.0/src/socialchimp/client.py +1176 -0
  22. socialchimp-0.1.0/src/socialchimp/contrib/__init__.py +26 -0
  23. socialchimp-0.1.0/src/socialchimp/contrib/django.py +537 -0
  24. socialchimp-0.1.0/src/socialchimp/contrib/fastapi.py +162 -0
  25. socialchimp-0.1.0/src/socialchimp/contrib/flask.py +222 -0
  26. socialchimp-0.1.0/src/socialchimp/contrib/shared.py +739 -0
  27. socialchimp-0.1.0/src/socialchimp/errors.py +227 -0
  28. socialchimp-0.1.0/src/socialchimp/events.py +760 -0
  29. socialchimp-0.1.0/src/socialchimp/features.py +545 -0
  30. socialchimp-0.1.0/src/socialchimp/http.py +809 -0
  31. socialchimp-0.1.0/src/socialchimp/models.py +539 -0
  32. socialchimp-0.1.0/src/socialchimp/platform.py +512 -0
  33. socialchimp-0.1.0/src/socialchimp/platforms/__init__.py +15 -0
  34. socialchimp-0.1.0/src/socialchimp/platforms/_meta.py +1418 -0
  35. socialchimp-0.1.0/src/socialchimp/platforms/bluesky.py +1234 -0
  36. socialchimp-0.1.0/src/socialchimp/platforms/facebook.py +1260 -0
  37. socialchimp-0.1.0/src/socialchimp/platforms/instagram.py +1754 -0
  38. socialchimp-0.1.0/src/socialchimp/platforms/mastodon.py +1162 -0
  39. socialchimp-0.1.0/src/socialchimp/platforms/pinterest.py +1393 -0
  40. socialchimp-0.1.0/src/socialchimp/platforms/threads.py +1838 -0
  41. socialchimp-0.1.0/src/socialchimp/platforms/tiktok.py +2074 -0
  42. socialchimp-0.1.0/src/socialchimp/platforms/x.py +1678 -0
  43. socialchimp-0.1.0/src/socialchimp/platforms/youtube.py +1797 -0
  44. socialchimp-0.1.0/src/socialchimp/py.typed +0 -0
  45. socialchimp-0.1.0/src/socialchimp/registry.py +293 -0
  46. socialchimp-0.1.0/src/socialchimp/storage.py +349 -0
  47. socialchimp-0.1.0/src/socialchimp/testing.py +1696 -0
  48. socialchimp-0.1.0/src/socialchimp/tokens.py +355 -0
  49. socialchimp-0.1.0/tests/__init__.py +1 -0
  50. socialchimp-0.1.0/tests/test_bluesky.py +1340 -0
  51. socialchimp-0.1.0/tests/test_client.py +1280 -0
  52. socialchimp-0.1.0/tests/test_contrib_django.py +672 -0
  53. socialchimp-0.1.0/tests/test_contrib_fastapi.py +257 -0
  54. socialchimp-0.1.0/tests/test_contrib_flask.py +306 -0
  55. socialchimp-0.1.0/tests/test_contrib_shared.py +626 -0
  56. socialchimp-0.1.0/tests/test_errors.py +105 -0
  57. socialchimp-0.1.0/tests/test_events.py +530 -0
  58. socialchimp-0.1.0/tests/test_facebook.py +1540 -0
  59. socialchimp-0.1.0/tests/test_features.py +487 -0
  60. socialchimp-0.1.0/tests/test_http.py +786 -0
  61. socialchimp-0.1.0/tests/test_instagram.py +1948 -0
  62. socialchimp-0.1.0/tests/test_mastodon.py +1255 -0
  63. socialchimp-0.1.0/tests/test_meta.py +1227 -0
  64. socialchimp-0.1.0/tests/test_models.py +306 -0
  65. socialchimp-0.1.0/tests/test_pinterest.py +1578 -0
  66. socialchimp-0.1.0/tests/test_platform.py +269 -0
  67. socialchimp-0.1.0/tests/test_registry.py +338 -0
  68. socialchimp-0.1.0/tests/test_storage.py +237 -0
  69. socialchimp-0.1.0/tests/test_testing.py +1518 -0
  70. socialchimp-0.1.0/tests/test_threads.py +1830 -0
  71. socialchimp-0.1.0/tests/test_tiktok.py +2121 -0
  72. socialchimp-0.1.0/tests/test_tokens.py +473 -0
  73. socialchimp-0.1.0/tests/test_x.py +1546 -0
  74. socialchimp-0.1.0/tests/test_youtube.py +1749 -0
  75. socialchimp-0.1.0/uv.lock +1227 -0
@@ -0,0 +1,44 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ concurrency:
9
+ group: ${{ github.workflow }}-${{ github.ref }}
10
+ cancel-in-progress: true
11
+
12
+ jobs:
13
+ check:
14
+ runs-on: ubuntu-latest
15
+ strategy:
16
+ fail-fast: false
17
+ matrix:
18
+ python-version: ["3.11", "3.12", "3.13"]
19
+
20
+ steps:
21
+ - uses: actions/checkout@v4
22
+
23
+ - name: Install uv
24
+ uses: astral-sh/setup-uv@v5
25
+ with:
26
+ enable-cache: true
27
+
28
+ - name: Set up Python ${{ matrix.python-version }}
29
+ run: uv python install ${{ matrix.python-version }}
30
+
31
+ - name: Install dependencies
32
+ run: uv sync --all-extras --dev
33
+
34
+ - name: Lint
35
+ run: uv run ruff check .
36
+
37
+ - name: Check formatting
38
+ run: uv run ruff format --check .
39
+
40
+ - name: Check types
41
+ run: uv run mypy
42
+
43
+ - name: Run tests
44
+ run: uv run pytest
@@ -0,0 +1,80 @@
1
+ name: Publish
2
+
3
+ # Publishes to PyPI when you publish a GitHub release.
4
+ #
5
+ # There is no API token anywhere. PyPI is told to trust this one workflow, in
6
+ # this one repository, and GitHub proves who it is at the moment it uploads.
7
+ # Nothing to store, nothing to leak, nothing to rotate.
8
+ #
9
+ # To set it up, add a publisher at https://pypi.org/manage/account/publishing/
10
+ # with these exact values:
11
+ #
12
+ # PyPI project name socialchimp
13
+ # Owner raghulj
14
+ # Repository name socialchimp
15
+ # Workflow name publish.yml
16
+ # Environment name pypi
17
+ #
18
+ # See docs/releasing.md for the whole procedure.
19
+
20
+ on:
21
+ release:
22
+ types: [published]
23
+ workflow_dispatch:
24
+
25
+ jobs:
26
+ # Publishing a broken release cannot be undone: PyPI never lets a version
27
+ # be replaced. So everything is checked again here, rather than trusting
28
+ # that the commit was green when it was tagged.
29
+ check:
30
+ runs-on: ubuntu-latest
31
+ strategy:
32
+ fail-fast: false
33
+ matrix:
34
+ python-version: ["3.11", "3.12", "3.13"]
35
+ steps:
36
+ - uses: actions/checkout@v4
37
+ - uses: astral-sh/setup-uv@v5
38
+ with:
39
+ enable-cache: true
40
+ - run: uv python install ${{ matrix.python-version }}
41
+ - run: uv sync --all-extras --dev
42
+ - run: uv run ruff check .
43
+ - run: uv run ruff format --check .
44
+ - run: uv run mypy
45
+ - run: uv run pytest
46
+
47
+ build:
48
+ needs: check
49
+ runs-on: ubuntu-latest
50
+ steps:
51
+ - uses: actions/checkout@v4
52
+ - uses: astral-sh/setup-uv@v5
53
+ - run: uv build
54
+
55
+ # Check the built files are actually uploadable before we try, so a
56
+ # bad description or a missing field fails here rather than half way
57
+ # through claiming the version number.
58
+ - run: uvx twine check --strict dist/*
59
+
60
+ - uses: actions/upload-artifact@v4
61
+ with:
62
+ name: packages
63
+ path: dist/
64
+
65
+ publish:
66
+ needs: build
67
+ runs-on: ubuntu-latest
68
+ environment:
69
+ name: pypi
70
+ url: https://pypi.org/p/socialchimp
71
+ permissions:
72
+ # Lets GitHub prove to PyPI that this workflow is what it says it is.
73
+ # This is what replaces the API token.
74
+ id-token: write
75
+ steps:
76
+ - uses: actions/download-artifact@v4
77
+ with:
78
+ name: packages
79
+ path: dist/
80
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,27 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ build/
6
+ dist/
7
+ .venv/
8
+ venv/
9
+
10
+ # Testing
11
+ .pytest_cache/
12
+ .coverage
13
+ coverage.xml
14
+ htmlcov/
15
+ .mypy_cache/
16
+ .ruff_cache/
17
+
18
+ # Editors
19
+ .vscode/
20
+ .idea/
21
+ *.swp
22
+ .DS_Store
23
+
24
+ # Secrets - never commit real credentials
25
+ .env
26
+ .env.*
27
+ !.env.example
@@ -0,0 +1,49 @@
1
+ # Checks that run before every commit and push.
2
+ #
3
+ # Install once after cloning:
4
+ # uv run pre-commit install --hook-type pre-commit --hook-type pre-push
5
+ #
6
+ # Fast checks (format, lint, types) run on commit.
7
+ # The test suite runs on push, because it is slower.
8
+
9
+ default_install_hook_types: [pre-commit, pre-push]
10
+
11
+ repos:
12
+ - repo: https://github.com/pre-commit/pre-commit-hooks
13
+ rev: v5.0.0
14
+ hooks:
15
+ - id: trailing-whitespace
16
+ - id: end-of-file-fixer
17
+ - id: check-yaml
18
+ - id: check-toml
19
+ - id: check-merge-conflict
20
+ - id: check-added-large-files
21
+ args: [--maxkb=512]
22
+ - id: detect-private-key
23
+ - id: mixed-line-ending
24
+ args: [--fix=lf]
25
+
26
+ - repo: https://github.com/astral-sh/ruff-pre-commit
27
+ rev: v0.8.6
28
+ hooks:
29
+ # Fix what can be fixed, then fail on what is left.
30
+ - id: ruff
31
+ args: [--fix]
32
+ - id: ruff-format
33
+
34
+ - repo: local
35
+ hooks:
36
+ - id: mypy
37
+ name: mypy (strict)
38
+ entry: uv run mypy
39
+ language: system
40
+ types: [python]
41
+ pass_filenames: false
42
+
43
+ - id: pytest
44
+ name: pytest (100% coverage required)
45
+ entry: uv run pytest
46
+ language: system
47
+ types: [python]
48
+ pass_filenames: false
49
+ stages: [pre-push]
@@ -0,0 +1,67 @@
1
+ # Changelog
2
+
3
+ Notable changes, newest first. Versions follow
4
+ [semantic versioning](https://semver.org): while this is 0.x, a change to the
5
+ middle number may break something.
6
+
7
+ ## 0.1.0 - 2026-08-31
8
+
9
+ The first release. Nine networks work end to end.
10
+
11
+ ### Networks
12
+
13
+ **Mastodon**, **Bluesky**, **Facebook Pages**, **Instagram**, **YouTube**,
14
+ **TikTok**, **X**, **Pinterest**, **Threads**.
15
+
16
+ Each one signs people in, keeps their token working, posts, and reports what
17
+ happened. What a network cannot do it says so, rather than approximating:
18
+ Bluesky has no scheduling, YouTube has no post of words alone, Pinterest has
19
+ no comments, Instagram cannot take an upload and needs a web address.
20
+
21
+ ### What is in it
22
+
23
+ - **One way to work with every network**, and direct access to any of them
24
+ when the shared way is not enough. Direct access still renews your token,
25
+ retries, and respects rate limits - only the request is yours.
26
+ - **Your app keeps its own database.** No models, no migrations. Five methods
27
+ in a class you write.
28
+ - **Tokens renewed before they run out**, under a lock so two workers cannot
29
+ renew at once. That matters on Bluesky, Pinterest and TikTok, which replace
30
+ the refresh token every time it is used: without the lock, whichever worker
31
+ loses is left holding a token the network has already thrown away, and that
32
+ account is disconnected until the person signs in again.
33
+ - **Updates the same shape either way** - pushed where a network supports it,
34
+ found by checking on a timer where it does not.
35
+ - **Helpers for Django, FastAPI and Flask.** Django works on ordinary
36
+ synchronous views and lets you write your storage as plain Django ORM code.
37
+ - **A test kit** so a network you write yourself can prove it behaves like
38
+ the ones here. You do not need a pull request to this repository to add a
39
+ network; publish a package, and socialchimp finds it.
40
+
41
+ ### Getting started
42
+
43
+ ```bash
44
+ pip install socialchimp
45
+ ```
46
+
47
+ Then [docs/getting-started.md](docs/getting-started.md), which goes from
48
+ nothing to a post on Mastodon in six steps.
49
+
50
+ ### Worth knowing
51
+
52
+ - **Facebook, Instagram, Threads, YouTube, TikTok, X and Pinterest all need
53
+ you to create the app by hand**, and several review it before it works.
54
+ That review is the slowest part of getting started, so begin it early.
55
+ [docs/platforms.md](docs/platforms.md) says what each one needs.
56
+ - **Three networks have a trap that makes working code look broken.** An
57
+ unaudited TikTok app posts everything as private. Pinterest on Trial shows
58
+ your pins only to you. X answers 403 when your plan does not allow
59
+ something. All three are called out where you will meet them.
60
+ - **The way platforms are written is now settled.** See
61
+ [the promise about changes](docs/adding-a-platform.md#what-we-promise-about-changes).
62
+
63
+ ### Quality
64
+
65
+ 1706 tests. 100% of lines and branches covered, enforced - the suite fails
66
+ below it. `mypy --strict` with no ignores anywhere. Checked on Python 3.11,
67
+ 3.12 and 3.13.
@@ -0,0 +1,76 @@
1
+ # Contributing
2
+
3
+ Thanks for helping. This page covers how to get set up and the three rules
4
+ that are not negotiable.
5
+
6
+ ## Getting set up
7
+
8
+ ```bash
9
+ git clone https://github.com/raghulj/socialchimp
10
+ cd socialchimp
11
+ uv sync --all-extras --dev
12
+ uv run pre-commit install --hook-type pre-commit --hook-type pre-push
13
+ ```
14
+
15
+ The hooks check formatting, style and types before each commit, and run the
16
+ tests before each push. That is deliberate: it means a broken push is hard to
17
+ do by accident.
18
+
19
+ ## The three rules
20
+
21
+ **1. Tests come first.** Write the failing test, watch it fail for the reason
22
+ you expect, then write the code. A test written afterwards tends to describe
23
+ what the code does rather than what it should do.
24
+
25
+ **2. Coverage stays at 100%.** `uv run pytest` fails below it. This is not
26
+ about the number - it is that a line nobody tested is a line nobody has ever
27
+ run, and in a library that talks to fifteen different networks those lines
28
+ pile up fast.
29
+
30
+ Coverage is a floor, not a finish line. A test that runs a line without
31
+ checking anything meaningful passes the gate and helps nobody. Worth trying
32
+ on anything tricky: break your own code on purpose and check a test notices.
33
+
34
+ **3. Types are strict.** `uv run mypy` passes with no `# type: ignore`. If a
35
+ type is hard to write, that is usually the design telling you something.
36
+
37
+ ## Language
38
+
39
+ Write in plain words, in code, docs and error messages alike.
40
+
41
+ Someone reading this library is usually in the middle of a problem: a token
42
+ stopped working, a post did not arrive. They should not also have to decode
43
+ our vocabulary. Say "the shared way", not "the abstraction layer". Say
44
+ "checking on a timer", not "polling-based virtual webhooks". If a name needs
45
+ a glossary, pick a different name.
46
+
47
+ Error messages should say what went wrong **and what to do about it**.
48
+
49
+ ## Comments
50
+
51
+ Comments explain *why*, not *what*. The code already says what it does.
52
+
53
+ The comments worth writing are the ones that stop someone undoing a decision
54
+ they do not understand - for example, why token renewal takes a lock and then
55
+ reads the connection a second time. Without the why, that reads like a
56
+ pointless extra query, and someone will remove it.
57
+
58
+ ## Before you push
59
+
60
+ ```bash
61
+ uv run ruff check . && uv run ruff format --check . && uv run mypy && uv run pytest
62
+ ```
63
+
64
+ Please do not push red. CI emails are nobody's idea of a good time.
65
+
66
+ ## Adding a network
67
+
68
+ You do not need to add it here. Publish your own package that registers
69
+ itself and socialchimp will find it. See [docs/adding-a-platform.md](docs/adding-a-platform.md).
70
+
71
+ If you would like it built in, open an issue first so we can agree where it
72
+ goes in the order - see [docs/PLAN.md](docs/PLAN.md).
73
+
74
+ ## Licence
75
+
76
+ By contributing you agree your work is released under the MIT licence.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Raghul Jagannathan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,159 @@
1
+ Metadata-Version: 2.5
2
+ Name: socialchimp
3
+ Version: 0.1.0
4
+ Summary: One simple way to connect your app to social networks.
5
+ Project-URL: Homepage, https://github.com/raghulj/socialchimp
6
+ Project-URL: Documentation, https://github.com/raghulj/socialchimp/tree/main/docs
7
+ Project-URL: Issues, https://github.com/raghulj/socialchimp/issues
8
+ Author-email: Raghul Jagannathan <raghulj@gmail.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: bluesky,django,fastapi,flask,instagram,mastodon,oauth,pinterest,social,threads,tiktok,twitter,youtube
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Classifier: Topic :: Internet :: WWW/HTTP
20
+ Classifier: Typing :: Typed
21
+ Requires-Python: >=3.11
22
+ Requires-Dist: httpx>=0.27
23
+ Provides-Extra: bluesky
24
+ Provides-Extra: django
25
+ Requires-Dist: django>=4.2; extra == 'django'
26
+ Provides-Extra: facebook
27
+ Provides-Extra: fastapi
28
+ Requires-Dist: fastapi>=0.110; extra == 'fastapi'
29
+ Provides-Extra: flask
30
+ Requires-Dist: flask>=3.0; extra == 'flask'
31
+ Provides-Extra: instagram
32
+ Provides-Extra: mastodon
33
+ Provides-Extra: pinterest
34
+ Provides-Extra: testing
35
+ Requires-Dist: pytest>=8.3; extra == 'testing'
36
+ Provides-Extra: threads
37
+ Provides-Extra: tiktok
38
+ Provides-Extra: x
39
+ Provides-Extra: youtube
40
+ Description-Content-Type: text/markdown
41
+
42
+ # socialchimp
43
+
44
+ [![CI](https://github.com/raghulj/socialchimp/actions/workflows/ci.yml/badge.svg)](https://github.com/raghulj/socialchimp/actions/workflows/ci.yml)
45
+ [![PyPI](https://img.shields.io/pypi/v/socialchimp?color=0b7285)](https://pypi.org/project/socialchimp/)
46
+ [![Python](https://img.shields.io/badge/python-3.11%20%7C%203.12%20%7C%203.13%20%7C%203.14-blue)](https://pypi.org/project/socialchimp/)
47
+ [![Coverage](https://img.shields.io/badge/coverage-100%25-brightgreen)](CONTRIBUTING.md)
48
+ [![Types](https://img.shields.io/badge/types-mypy%20strict-blue)](pyproject.toml)
49
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
50
+ [![Licence](https://img.shields.io/badge/licence-MIT-black)](LICENSE)
51
+
52
+ One simple way to connect your app to social networks.
53
+
54
+ > **Status: 0.1.0, the first release.** All nine networks below work. The way
55
+ > platforms are written is now settled - see
56
+ > [the promise about changes](docs/adding-a-platform.md#what-we-promise-about-changes)
57
+ > before you write your own.
58
+
59
+ **Mastodon · Bluesky · Facebook Pages · Instagram · YouTube · TikTok · X · Pinterest · Threads**
60
+
61
+ ---
62
+
63
+ ## What it does
64
+
65
+ Your app needs to let people connect their social accounts, then post for
66
+ them and read what happens. Every network does this differently. socialchimp
67
+ gives you one way to do it, and gets out of the way when you need the network's
68
+ own features.
69
+
70
+ - **Connect accounts.** Sign in with Mastodon, Bluesky, Facebook, Instagram,
71
+ YouTube, TikTok, X, Pinterest, Threads and more.
72
+ - **Keep tokens working.** Refresh them before they expire, safely, even when
73
+ several workers run at once.
74
+ - **Post and read.** Text, pictures, video. Read posts and their numbers back.
75
+ - **Know what happened.** Comments and likes reach you the same way whether the
76
+ network pushes them to you or we have to check on a timer.
77
+
78
+ ## What it does not do
79
+
80
+ - **It does not touch your database.** No models, no migrations. You write a
81
+ small storage class, socialchimp hands you data to save. Your schema stays
82
+ yours, and it works the same on Django, FastAPI, Flask, or nothing at all.
83
+ - **It does not pretend networks are the same.** Pinterest needs a board.
84
+ Bluesky cannot schedule. YouTube has no text-only post. Where networks
85
+ differ, the API says so instead of guessing for you.
86
+
87
+ ---
88
+
89
+ ## Install
90
+
91
+ ```bash
92
+ pip install socialchimp
93
+ ```
94
+
95
+ Add your framework if you want the ready-made routes:
96
+
97
+ ```bash
98
+ pip install "socialchimp[django]" # or [fastapi], or [flask]
99
+ ```
100
+
101
+ ## A first look
102
+
103
+ ```python
104
+ from socialchimp import SocialChimp, Post
105
+
106
+ sc = SocialChimp(storage=MyStorage())
107
+
108
+ # Post to a connected account.
109
+ account = sc.account(connection_id)
110
+ result = await account.post(Post(text="Hello from socialchimp"))
111
+ print(result.url)
112
+ ```
113
+
114
+ Need something only that network can do? Same connection, direct access:
115
+
116
+ ```python
117
+ await account.direct.post(
118
+ "/api/v1/statuses",
119
+ json={"status": "Hello", "visibility": "unlisted"},
120
+ )
121
+ ```
122
+
123
+ Tokens, retries and rate limits are still handled for you. Only the request
124
+ is yours.
125
+
126
+ ---
127
+
128
+ ## Documentation
129
+
130
+ - [Getting started](docs/getting-started.md) - from nothing to a post
131
+ - [Networks](docs/platforms.md) - what each one can do, and what it needs
132
+ - [Frameworks](docs/frameworks.md) - ready-made routes for Django,
133
+ FastAPI and Flask
134
+ - [Adding a platform](docs/adding-a-platform.md) - a network we do not
135
+ support yet
136
+ - [Plan](docs/PLAN.md) - what is built and what is coming
137
+ - [Changelog](CHANGELOG.md) - what changed, and what it means for you
138
+ - [Releasing](docs/releasing.md) - how a release goes out
139
+ - [Examples](examples/) - runnable programs
140
+
141
+ ## Contributing
142
+
143
+ Contributions are welcome. A few things to know first:
144
+
145
+ - **Tests come first.** Write the failing test, then make it pass.
146
+ - **Coverage must stay at 100%.** CI fails below it.
147
+ - **Types must be strict.** `mypy --strict` with no ignores.
148
+
149
+ ```bash
150
+ git clone https://github.com/raghulj/socialchimp
151
+ cd socialchimp
152
+ uv sync --all-extras --dev
153
+ uv run pre-commit install --hook-type pre-commit --hook-type pre-push
154
+ uv run pytest
155
+ ```
156
+
157
+ ## Licence
158
+
159
+ MIT. See [LICENSE](LICENSE).
@@ -0,0 +1,118 @@
1
+ # socialchimp
2
+
3
+ [![CI](https://github.com/raghulj/socialchimp/actions/workflows/ci.yml/badge.svg)](https://github.com/raghulj/socialchimp/actions/workflows/ci.yml)
4
+ [![PyPI](https://img.shields.io/pypi/v/socialchimp?color=0b7285)](https://pypi.org/project/socialchimp/)
5
+ [![Python](https://img.shields.io/badge/python-3.11%20%7C%203.12%20%7C%203.13%20%7C%203.14-blue)](https://pypi.org/project/socialchimp/)
6
+ [![Coverage](https://img.shields.io/badge/coverage-100%25-brightgreen)](CONTRIBUTING.md)
7
+ [![Types](https://img.shields.io/badge/types-mypy%20strict-blue)](pyproject.toml)
8
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
9
+ [![Licence](https://img.shields.io/badge/licence-MIT-black)](LICENSE)
10
+
11
+ One simple way to connect your app to social networks.
12
+
13
+ > **Status: 0.1.0, the first release.** All nine networks below work. The way
14
+ > platforms are written is now settled - see
15
+ > [the promise about changes](docs/adding-a-platform.md#what-we-promise-about-changes)
16
+ > before you write your own.
17
+
18
+ **Mastodon · Bluesky · Facebook Pages · Instagram · YouTube · TikTok · X · Pinterest · Threads**
19
+
20
+ ---
21
+
22
+ ## What it does
23
+
24
+ Your app needs to let people connect their social accounts, then post for
25
+ them and read what happens. Every network does this differently. socialchimp
26
+ gives you one way to do it, and gets out of the way when you need the network's
27
+ own features.
28
+
29
+ - **Connect accounts.** Sign in with Mastodon, Bluesky, Facebook, Instagram,
30
+ YouTube, TikTok, X, Pinterest, Threads and more.
31
+ - **Keep tokens working.** Refresh them before they expire, safely, even when
32
+ several workers run at once.
33
+ - **Post and read.** Text, pictures, video. Read posts and their numbers back.
34
+ - **Know what happened.** Comments and likes reach you the same way whether the
35
+ network pushes them to you or we have to check on a timer.
36
+
37
+ ## What it does not do
38
+
39
+ - **It does not touch your database.** No models, no migrations. You write a
40
+ small storage class, socialchimp hands you data to save. Your schema stays
41
+ yours, and it works the same on Django, FastAPI, Flask, or nothing at all.
42
+ - **It does not pretend networks are the same.** Pinterest needs a board.
43
+ Bluesky cannot schedule. YouTube has no text-only post. Where networks
44
+ differ, the API says so instead of guessing for you.
45
+
46
+ ---
47
+
48
+ ## Install
49
+
50
+ ```bash
51
+ pip install socialchimp
52
+ ```
53
+
54
+ Add your framework if you want the ready-made routes:
55
+
56
+ ```bash
57
+ pip install "socialchimp[django]" # or [fastapi], or [flask]
58
+ ```
59
+
60
+ ## A first look
61
+
62
+ ```python
63
+ from socialchimp import SocialChimp, Post
64
+
65
+ sc = SocialChimp(storage=MyStorage())
66
+
67
+ # Post to a connected account.
68
+ account = sc.account(connection_id)
69
+ result = await account.post(Post(text="Hello from socialchimp"))
70
+ print(result.url)
71
+ ```
72
+
73
+ Need something only that network can do? Same connection, direct access:
74
+
75
+ ```python
76
+ await account.direct.post(
77
+ "/api/v1/statuses",
78
+ json={"status": "Hello", "visibility": "unlisted"},
79
+ )
80
+ ```
81
+
82
+ Tokens, retries and rate limits are still handled for you. Only the request
83
+ is yours.
84
+
85
+ ---
86
+
87
+ ## Documentation
88
+
89
+ - [Getting started](docs/getting-started.md) - from nothing to a post
90
+ - [Networks](docs/platforms.md) - what each one can do, and what it needs
91
+ - [Frameworks](docs/frameworks.md) - ready-made routes for Django,
92
+ FastAPI and Flask
93
+ - [Adding a platform](docs/adding-a-platform.md) - a network we do not
94
+ support yet
95
+ - [Plan](docs/PLAN.md) - what is built and what is coming
96
+ - [Changelog](CHANGELOG.md) - what changed, and what it means for you
97
+ - [Releasing](docs/releasing.md) - how a release goes out
98
+ - [Examples](examples/) - runnable programs
99
+
100
+ ## Contributing
101
+
102
+ Contributions are welcome. A few things to know first:
103
+
104
+ - **Tests come first.** Write the failing test, then make it pass.
105
+ - **Coverage must stay at 100%.** CI fails below it.
106
+ - **Types must be strict.** `mypy --strict` with no ignores.
107
+
108
+ ```bash
109
+ git clone https://github.com/raghulj/socialchimp
110
+ cd socialchimp
111
+ uv sync --all-extras --dev
112
+ uv run pre-commit install --hook-type pre-commit --hook-type pre-push
113
+ uv run pytest
114
+ ```
115
+
116
+ ## Licence
117
+
118
+ MIT. See [LICENSE](LICENSE).