Skip to content

Releases: david-lev/pywa

1.25.0

15 Aug 16:38
Compare
Choose a tag to compare

What's Changed

Update with pip: pip3 install -U pywa

  • [handlers] adding priority
  • [client] adding QR methods (create update get and delete)
  • [client] adding get_flow_metrics method
  • [flows] adding to DataSource support for images/colors
  • [flows] support datetime objs in DatePicker
  • [flows] support Screen when using .data_key_of(...) and .form_ref_of(...)
  • [flows] update flow json with indent and without ensuring ascii
  • [flows] adding health_status to FlowDetails
from pywa import WhatsApp, types

wa = WhatsApp(...)

@wa.on_message(filters.text, priority=2)
def one(_: WhatsApp, m: types.Message):
    ...

@wa.on_message(filters.text, priority=3) # will be called before `one`
def two(_: WhatsApp, m: types.Message):
    ...

wa.create_qr_code(prefilled_message="Hi, I am interested in your product", image_type="SVG")

wa.get_flow_metrics(
    flow_id=...,
    metric_name=types.FlowMetricName.ENDPOINT_REQUEST_COUNT,
    granularity=types.FlowMetricGranularity.DAY,
    since=datetime.date(2024, 8, 1),
)

flow = FlowJSON(
    screens=[
        screen_1 := Screen(
            data=[name := ScreenData(key="name", example="David")], # data key in screen_1
            layout=...
        ),
        screen_2 := Screen(
            layout=Layout(
                children=[
                    TextHeading(text=name.data_key_of(screen_1)), # reference to data key in screen_1
                    date := DatePicker(
                        name="date",
                        label="When?",
                        min_date=datetime.date(2024, 8, 1), # date obj in DatePicker 
                        max_date=datetime.date(2024, 8, 30),
                    )
                ]
            ),
        )
    ]
)

Full Changelog: 1.24.0...1.25.0

1.24.0

26 Jul 11:38
Compare
Choose a tag to compare

What's Changed

Update with pip: pip3 install -U pywa

  • [server] validating X-Hub-Signature-256 header
  • [requirements] removing requests
  • [server] default callback url registration delay to 3 sec
wa = WhatsApp(
    validate_updates=True, # Default: True
    app_secret="122hifewyhf9we372d93676",
    ...
)

Full Changelog: 1.23.0...1.24.0

1.23.0

13 Jul 21:27
Compare
Choose a tag to compare

What's Changed

Update with pip: pip3 install -U pywa

  • [client] allowing to manage multiple numbers from the same client (Partner solutions)
  • [flows] adding .respond() shortcut for FlowRequest
  • [flows] allowing body in FlowResponseError subclasses
from pywa import WhatsApp, types, filters

wa = WhatsApp(token="xyzxyz", ...) # `phone_id` is now optional

wa.send_message(
    sender=..., # now you can specify sender
    to=...,
    text="Hello from PyWa!"
)

@wa.on_message(filters.text.command("start"))
def on_start(_: WhatsApp, msg: types.Message):
    if msg.recipient == ...:  # or check the recipient
        ...
    elif msg.recipient == ...:
        ...
    msg.reply(...) # .reply() is automatically replaying to the sender
from pywa import WhatsApp, types

wa = WhatsApp(...)

@wa.on_flow_request("/my-flow")
def my_flow_handler(_: WhatsApp, req: types.FlowRequest) -> types.FlowResponse:
    return req.respond( # instead of instantiating FlowResponse with req.version
        screen="SIGN_UP",
        data={}
    )

Full Changelog: 1.22.0...1.23.0

1.22.0

16 Jun 16:21
Compare
Choose a tag to compare

What's Changed

Update with pip: pip3 install -U pywa

  • [handlers] introducing new way to help split flow endpoint logic to multiple handlers (see example)
  • [client] adding add_flow_request_handler method to register FlowRequestHandlers
  • [flows] pop flow_token from FlowCompletion.response
  • [docs] update examples
from pywa import WhatsApp, types

wa = WhatsApp(...)

@wa.on_flow_request("/my-flow")
def my_flow_handler(_: WhatsApp, flow: types.FlowRequest) -> types.FlowResponse | None:
    ...

@my_flow_handler.on(action=types.FlowRequestActionType.INIT)
def on_init(_: WhatsApp, request: types.FlowRequest) -> types.FlowResponse:
    ...

@my_flow_handler.on(action=types.FlowRequestActionType.DATA_EXCHANGE, screen="SIGN_UP")
def on_signup(_: WhatsApp, request: types.FlowRequest) -> types.FlowResponse:
    ...

@my_flow_handler.on(
    action=types.FlowRequestActionType.DATA_EXCHANGE,
    screen="LOGIN",
    data_filter=lambda _, data: not user_repository.exists(data["email"]),
)
def if_not_registered(_: WhatsApp, request: types.FlowRequest) -> types.FlowResponse | None:
    ...

Full Changelog: 1.21.0...1.22.0

1.21.0

14 Jun 12:20
Compare
Choose a tag to compare

What's Changed

Update with pip: pip3 install -U pywa

Caution

  • [server] This version drops support for non-asynchronous WSGI applications (Flask without asgiref)
  • [flows] version is now required in FlowJSON
  • [flows] added new components PhotoPicker, DocumentPicker, If and Switch
  • [flows] added .data_key_of and .form_ref_of to refer from other screens
  • [flows] added description to CheckboxGroup and to RadioButtonsGroup
  • [utils] adding flow_request_media_decryptor function to decrypt medias from flow requests
  • [client] allow updating flow application id with update_flow_metadata
  • [server] remove event loop
  • [docs] update examples
  • [version] bump FLOW_JSON version to 4.0
from pywa import WhatsApp, utils, types
from pywa.types.flows import *

wa = WhatsApp(...)

my_flow = FlowJSON(
    version="4.0",
    screens=[
        Screen(
            id="UPLOAD_DRIVER_LICENSE",
            title="Upload Driver License",
            layout=Layout(
                children=[
                    doc := DocumentPicker(
                        name="driver_license",
                        label="Driver License",
                        min_uploaded_documents=1,
                        max_uploaded_documents=1,
                        allowed_mime_types=["application/pdf", "image/jpeg"],
                    ),
                    Footer(
                        label="Next",
                        enabled=True,
                        on_click_action=Action(
                            name=FlowActionType.DATA_EXCHANGE,
                            payload={"doc": doc.form_ref_of("UPLOAD_DRIVER_LICENSE")},
                        ),
                    ),
                ]
            )
        )
    ]
)


@wa.on_flow_request("/flow")
def on_flow_request(_, flow: types.FlowRequest):
    media_id, filename, media_bytes = utils.flow_request_media_decryptor_sync(flow.data["doc"])
    with open(filename, "wb") as f:
        f.write(media_bytes)
    ...

Full Changelog: 1.20.2...1.21.0

1.20.2

02 Jun 12:24
Compare
Choose a tag to compare

What's Changed

Update with pip: pip3 install -U pywa

  • [pywa] adding official support for async (limited support for now)
  • [server] expose webhook_challenge_handler, webhook_update_handler and get_flow_request_handler for custom server implementations
  • [server] improve continue/stop handling
  • [client] adding skip_duplicate_updates when callbacks take too long to return (~25s), defaults to True
  • [client,handlers] allow to override continue_handling
# wa.py
from pywa_async import WhatsApp, types  # Import from `pywa_async` instead of `pywa`
import fastapi

fastapi_app = FastAPI()
wa = WhatsApp(..., server=fastapi_app)

@wa.on_message()
async def echo_media(_: WhatsApp, msg: types.Message):
    await msg.reply("I'm using PyWa async!")

Run with uvicorn:

uvicorn wa:fastapi_app

Full Changelog: 1.18.1...1.20.2

1.19.0-rc.3

23 May 21:01
Compare
Choose a tag to compare
1.19.0-rc.3 Pre-release
Pre-release

What's Changed

Update with pip: pip3 install -U pywa==1.19.0-rc.3

  • [api] fix uploads
  • [server] expose webhook_challenge_handler, webhook_update_handler and flow_request_handler

Full Changelog: 1.19.0-rc.2...1.19.0-rc.3

1.19.0-rc.2

16 May 21:24
Compare
Choose a tag to compare
1.19.0-rc.2 Pre-release
Pre-release

What's Changed

Update with pip: pip3 install -U pywa==1.19.0-rc.2

  • [client] adding skip_duplicate_updates when callbacks take too long to return (~25s), defaults to True
  • [client,handlers] allow to override continue_handling
  • [message] fix async constructors
  • [api] remove requests_toolbelt from deps
  • [handlers] fix dynamic field name when factory_before_filters

Full Changelog: 1.19.0-rc.1...1.19.0-rc.2

1.19.0-rc.1

08 May 18:42
Compare
Choose a tag to compare
1.19.0-rc.1 Pre-release
Pre-release

What's Changed

Update with pip: pip3 install -U pywa==1.19.0-rc.1

  • [async] adding beta support for async!
from pywa_async import WhatsApp, types  # Import from `pywa_async` instead of `pywa`

wa = WhatsApp(...)

@wa.on_message(filters.media)
async def echo_media(_: WhatsApp, message: types.Message):
    await message.copy(to=message.sender)

Full Changelog: 1.18.1...1.19.0-rc.1

1.18.1

05 May 20:00
Compare
Choose a tag to compare

What's Changed

Update with pip: pip3 install -U pywa

  • [client] fix document filename

Full Changelog: 1.18.0...1.18.1