Metadata-Version: 2.2
Name: make_post_sell
Version: 1.5.1
Summary: Make Post Sell
Home-page: https://www.makepostsell.com
Author: Russell Ballestrini
Author-email: russell@ballestrini.net
Keywords: make post sell web pyramid pylons ecommerce digital downloads physical goods content marketing youtube alternative
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: 3.15
Classifier: Programming Language :: Python
Classifier: Framework :: Pyramid
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application
Requires-Dist: six
Requires-Dist: setuptools<81
Requires-Dist: plaster_pastedeploy
Requires-Dist: pyramid
Requires-Dist: pyramid_jinja2
Requires-Dist: pyramid_debugtoolbar
Requires-Dist: waitress
Requires-Dist: pyramid_retry
Requires-Dist: pyramid_tm
Requires-Dist: SQLAlchemy
Requires-Dist: SQLAlchemy-Utils
Requires-Dist: transaction
Requires-Dist: zope.sqlalchemy
Requires-Dist: alembic
Requires-Dist: boto3
Requires-Dist: python-slugify
Requires-Dist: bcrypt
Requires-Dist: stripe
Requires-Dist: paypalrestsdk
Requires-Dist: Adyen
Requires-Dist: dkimpy
Requires-Dist: dkimpy[ed25519]
Requires-Dist: markdown
Requires-Dist: ago
Requires-Dist: miniuri
Requires-Dist: bleach>=6.0.0
Requires-Dist: bleach-allowlist
Requires-Dist: beautifulsoup4
Requires-Dist: html5lib
Requires-Dist: requests>=2.28
Provides-Extra: dev
Requires-Dist: setuptools<81; extra == "dev"
Requires-Dist: bpython; extra == "dev"
Requires-Dist: pyramid_bpython; extra == "dev"
Requires-Dist: waitress; extra == "dev"
Provides-Extra: prod
Requires-Dist: uwsgi; extra == "prod"
Requires-Dist: psycopg2; extra == "prod"
Provides-Extra: test
Requires-Dist: pytest; extra == "test"
Requires-Dist: pytest-cov; extra == "test"
Requires-Dist: pytest-timeout; extra == "test"
Requires-Dist: pytest-xdist; extra == "test"
Requires-Dist: nose; extra == "test"
Requires-Dist: mock; extra == "test"
Requires-Dist: WebTest; extra == "test"
Requires-Dist: fakeredis; extra == "test"
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: home-page
Dynamic: keywords
Dynamic: provides-extra
Dynamic: requires-dist
Dynamic: summary

Make Post Sell
==============

The `Make Post Sell <https://www.makepostsell.com>`_ monolith platform service.

You can use the SaaS or self-host! Accepts credit cards (Stripe), PayPal, Monero (XMR), and Dogecoin (DOGE) payments.

Our `blog acts as our user guide <https://blog.makepostsell.com/>`_ & also uses ``make_post_sell``!

| `Source Code <https://git.unturf.com/engineering/make-post-sell/make_post_sell>`_ | `PyPI <https://pypi.org/project/make-post-sell/>`_ | `SaaS <https://my.makepostsell.com>`_ |

Features
--------

* **Multi-tenant SaaS** — each shop gets its own subdomain or custom domain
* **Payments** — Stripe, PayPal, Adyen, Monero (XMR), Dogecoin (DOGE);
  payment webhooks verify signatures and fail closed
* **Coupons & Gift Cards** — dollar/percent-off coupons with redemption
  limits; per-shop gift cards with balances and transactions
* **Auctions & Make-an-Offer** — eBay-style bidding and negotiated offers
  per product (``pricing_mode``), live updates over bounded SSE
* **Shop Home Layouts & Categories** — flat grid, filter chips, or
  sectioned lanes; tags derived linguistically from titles+descriptions
  (suggest-then-approve, auto-hydrate on edit)
* **Creator Analytics** — anonymous page signals (no cookies, no IPs),
  per-shop and per-product dashboards, referrer/device/engagement metrics
* **Watch Mode** — continuous media playback with DJ crossfade transitions, discovery ring, queue management, and autoplay
* **Pop-out Player** — draggable media window with keyboard shortcuts, ``/random`` and ``/tv`` endpoints
* **Email Subscriptions** — digest emails (immediately, daily, weekly) with @mention notifications
* **Feeds** — RSS, Atom, and sitemap generation per shop
* **AJAX Comments** — real-time comment posting without page reload, preserves media playback
* **Related Content** — Jaccard similarity ranking with thumbnails
* **Bring Your Own Bucket** — shops can point uploads at their own
  S3-compatible bucket + CDN; media never streams through the app server
* **REST API v1** — HMAC-signed product/content creation and file upload
* **21-Day Trials** — per-shop trial with grandfathering for existing shops
* **Feature Kill Switches** — ship features dark, flip per-deployment via env
* **Lazy Carts** — in-memory until a product is added, no empty rows from bots
* **CSS Grid Lanes** — optional masonry layout per shop
* **Vanilla JS** — no jQuery, no framework dependencies; capability-driven
  presentation (every flow works without JavaScript)
* **Public Domain** — all contributed code is placed in the public domain

See ``CHANGELOG.rst`` for detailed release history, ``docs/architecture.md``
for the feature/ticket matrix, and ``docs/roadmap-scale-and-operators.md``
for the current audit findings and prioritized roadmap (scale readiness,
operator tooling, profitability).


Quick Start: Operating a Server with PyPI or Source Code
==========================================================

Before you start, navigate to the directory where you want to install ``make_post_sell`` database & files.

This Makefile-based workflow lets you choose between installing ``make_post_sell`` from PyPI packages or directly from the source code (editable mode). Both flows create a virtual environment in ``./env`` and store configuration and SQLite data in the persistent ``./data`` directory.

1. **Install make_post_sell**

   - **PyPI Installation:**  
     Download the Makefile and run::
     
         wget "https://git.unturf.com/engineering/make-post-sell/make_post_sell/-/raw/master/Makefile"
         make install-from-pypi

   - **Source Installation (Editable Mode):**  
     Clone the repository and run::
     
         git clone ssh://git@git.unturf.com:2222/engineering/make-post-sell/make_post_sell.git
         make install-from-source

   - **Production Installation (Non‑Editable):**  
     For production use (non‑editable even from source), run::
     
         git clone ssh://git@git.unturf.com:2222/engineering/make-post-sell/make_post_sell.git
         make install-from-source-prod

2. **Activate the Virtual Environment**

   Before running any commands, activate the virtual environment::
   
         source env/bin/activate

3. **Start the Development Server**

   You'll want to configure the system in ``data/development.ini``.

   Typically I control most stuff with environment vars, for example ``vars.sh``::

         # boto3 style credentials for s3/digital-ocean spaces.
         # this is for storing content & physical products.
         export MPS_APP_MAIN_BUCKET="removed"
         export MPS_APP_SECURE_UPLOADS_ACCESS_KEY="removed"
         export MPS_APP_SECURE_UPLOADS_SECRET_KEY="removed"

         # stripe keys for collecting credit cards & crypto.
         # NOTE: These are used by tests, shops configure their own keys in the UI
         export MPS_TEST_STRIPE_PUBLIC_API_KEY="pk_test_removed"
         export MPS_TEST_STRIPE_SECRET_API_KEY="sk_test_removed"

         # the root domain acts as a SaaS for many shop domains!
         export MAKE_POST_SELL_ROOT_DOMAIN="example.com"
         export MAKE_POST_SELL_ROOT_URL="http://example.com:6501"
         
         # optional: email for the root domain owner
         export MAKE_POST_SELL_DOMAIN_OWNER_EMAIL="admin@example.com"

         # optional: DKIM email signing (commented out by default)
         # export MPS_APP_DKIM_PRIVATE_KEY_PATH="/path/to/dkim/private.key"
         # export MPS_APP_DKIM_SELECTOR="selector"

         # production: Stripe webhook signing secret. Payment webhooks
         # fail closed — without this, Stripe webhook recovery (unlocking
         # purchases when a checkout dies after the charge) returns 403.
         # export MPS_STRIPE_WEBHOOK_SECRET="whsec_..."

   With the virtual environment active, start the server::

         source vars.sh
         make serve

   Then browse to `http://127.0.0.1:6501/ <http://127.0.0.1:6501/>`_ to view the app.



Running Tests
-------------

We use `pytest` (parallel via ``pytest-xdist``, isolated DB per worker).
Tests need environment variables (Stripe test keys etc.), so source them
first:

.. code-block:: bash

 source vars.sh
 make test

The suite has three layers, and new features are expected to land with
coverage in all three: unit (``test_models.py``, no DB), integration
(``test_integration.py``), and functional (``test_functional.py``,
full WSGI app through ``webtest``).


SQL Migrations
===============

If your deployment is brand new, you don't need to run any migrations.

Otherwise, it should be safe to run this at anytime to catch your database up
(``make backup-db`` first — it's cheap):

.. code-block:: bash

 make backup-db
 make migrate

To look at the current revision and the history:

.. code-block:: bash

 make migration-status

To cut a new migration script:

.. code-block:: bash

 make migration m="add foo column to bar table"

**Always use** ``make migration`` — it autogenerates a cryptographically
unique revision ID by comparing your models against the database. Never
hand-write a migration file or invent a revision ID; a made-up ID corrupts
the migration chain and breaks deploys everywhere.

Two rules for editing the generated script before you commit it:

* Migrations must be **idempotent** — ``make init-db`` creates all tables
  from models, so guard ``create_table`` with a table-exists check and
  ``add_column`` with a column-exists check (copy the ``_table_exists`` /
  ``_column_exists`` helpers from any recent file in
  ``make_post_sell/scripts/alembic/versions/``).
* SQLite needs ``server_default="..."`` (raw SQL string) for NOT NULL
  columns added to existing tables — ``default=`` does nothing for
  existing rows.

misc
====

You may source the new Python virtual environment during development:

.. code-block:: bash

 # source env/bin/activate.fish
 . env/bin/activate


Python Pyramid Shell
==========================

If you want to use an interactive Python interpreter to interact with Make Post Sell app/models & DB:

.. code-block:: bash

 pshell development.ini

For example, we needed to migrate production data using this script:

.. code-block:: python

 # begin the database transaction.
 request.tm.begin()

 suses = models.stripe_user_shop.get_all_stripe_user_shop_objects(request.dbsession)
 for sus in suses:
     try:
         sus.active_card_id = sus.stripe_customer_default_source.id
         request.dbsession.add(sus)
     except AttributeError:
         pass

 # flush / commit all changes stored the the sqlachemy session.
 request.dbsession.flush()

 # commit/close the database transaction to really make changes.
 request.tm.commit()


Contributing
===================

* Establish communication with Russell or another admin to bless your git.unturf.com gitlab account & put you into the proper roles.
* Russell should see your account request but due to spam you have to ask him directly for approval via email or some other means of comms.
* Clone repo & make commits
* Create merge requests, we automatically run the unit & headless functional tests on each commit
* On merge we release to the production site & see the change across users.
* If you touch ``requirements.py3.txt``, run ``make pins-lock`` and commit
  the regenerated ``requirements-prod.lock`` in the same MR — CI builds the
  production virtualenv from the lock file, so a forgotten lock ships an
  artifact missing your dependency (tests still pass; prod imports fail).

Optionally, format your code.

This is not set in stone, but if you want to use a formatter this is the path for now!

**Python**
  black (manual)

**Jinja2**
  None (not needed, neither is an HTML formatter)

**JavaScript**
  Prettier or biome (manual)

**CSS**
  Prettier or biome (manual)


Licence
==============================================

All contributed code is placed in the public domain.

source code: `https://git.unturf.com/engineering/make-post-sell/make_post_sell <https://git.unturf.com/engineering/make-post-sell/make_post_sell>`_

MakePostSell & make-post-sell are trademarked, do not misrepresent the brand.

Feel free to white label any code or themes into your own brand.

**Original Developer:**  
`Russell Ballestrini <https://russell.ballestrini.net>`_
