Skip to content

Commit

Permalink
Added confirm/opt-in subscriber via API.
Browse files Browse the repository at this point in the history
  • Loading branch information
mikeckennedy committed Jan 21, 2024
1 parent 039693b commit df7867c
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 5 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ up: bool = listmonk.is_healthy()

# Read data about your lists
lists: list[] = listmonk.lists()
list: MailingList = listmonk.list_by_id(list_id=7)
the_list: MailingList = listmonk.list_by_id(list_id=7)

# Various ways to access existing subscribers
subscribers: list[] = listmonk.subscribers(list_id=9)
Expand All @@ -58,7 +58,10 @@ new_subscriber = listmonk.create_subscriber(
# Change the email, custom rating, and add to lists 4 & 6, remove from 5.
subscriber.email = 'newemail@some.domain'
subscriber.attribs['rating'] = 7
updated_subscriber = listmonk.update_subscriber(subscriber, {4, 6}, {5})
subscriber = listmonk.update_subscriber(subscriber, {4, 6}, {5})

# Confirm single-opt-ins via the API (e.g. for when you manage that on your platform)
listmonk.confirm_optin(subscriber.uuid, the_list.uuid)

# Disable then re-enable a subscriber
subscriber = listmonk.disable_subscriber(subscriber)
Expand Down
10 changes: 7 additions & 3 deletions example_client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
for lst in lists:
print(f'{lst.name} list: {lst}')

lst = listmonk.list_by_id(6)
print(f'List by ID: {lst}')
the_list = listmonk.list_by_id(test_list_id)
print(f'List by ID: {the_list}')

print()
subscribers = listmonk.subscribers(list_id=test_list_id)
Expand Down Expand Up @@ -68,9 +68,13 @@
subscriber.attribs['rating'] = 7

# TODO: Choose list IDs from your instance (can be seen in the UI or from the listing above)
updated_subscriber = listmonk.update_subscriber(subscriber, {4, 6}, {5})
to_add = {the_list.id} # Add all the lists here: {1, 7, 11}
remove_from = set() # Same as above
updated_subscriber = listmonk.update_subscriber(subscriber, to_add, remove_from)
print(f'Updated subscriber: {updated_subscriber}')

print(f'Subscriber confirmed?: {listmonk.confirm_optin(subscriber.uuid, the_list.uuid)}')

updated_subscriber.attribs['subscription_note'] = \
"They asked to be unsubscribed so we disabled their account, but no block-listing yet."

Expand Down
2 changes: 2 additions & 0 deletions listmonk/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from listmonk import impl
from listmonk import models # noqa: F401, E402
from listmonk.impl import confirm_optin # noqa: F401, E402
from listmonk.impl import create_subscriber, delete_subscriber, update_subscriber # noqa: F401, E402
from listmonk.impl import disable_subscriber, enable_subscriber, block_subscriber # noqa: F401, E402
from listmonk.impl import is_healthy # noqa: F401, E402
Expand All @@ -22,5 +23,6 @@
create_subscriber, delete_subscriber, update_subscriber,
disable_subscriber, enable_subscriber, block_subscriber,
send_transactional_email,
confirm_optin,
is_healthy,
]
41 changes: 41 additions & 0 deletions listmonk/impl/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,47 @@ def delete_subscriber(email: Optional[str] = None, overriding_subscriber_id: Opt

# endregion


# region def confirm_optin(subscriber_uuid: str, list_uuid: str) -> bool

def confirm_optin(subscriber_uuid: str, list_uuid: str) -> bool:
global core_headers
validate_state(url=True, user=True)
if not subscriber_uuid:
raise ValueError("subscriber_uuid is required")
if not list_uuid:
raise ValueError("list_uuid is required")

#
# If there is a better endpoint / API for this, please let me know.
# We're reduced to basically submitting the form via web scraping.
#
payload = {
'l': list_uuid,
'confirm': 'true',

}
url = f"{url_base}{urls.opt_in.format(subscriber_uuid=subscriber_uuid)}"
resp = httpx.post(url, data=payload, follow_redirects=True)
resp.raise_for_status()

success_phrases = {
# New conformation was created now.
'Subscribed successfully.',
'Confirmed',

# They were already confirmed somehow previously.
'no subscriptions to confirm',
'No subscriptions'
}

text = resp.text or ''
return any(p in text for p in success_phrases)


# endregion


# region def update_subscriber(subscriber: models.Subscriber, add_to_lists: set[int], remove_from_lists: set[int])

def update_subscriber(subscriber: models.Subscriber, add_to_lists: set[int] = None, remove_from_lists: set[int] = None,
Expand Down
1 change: 1 addition & 0 deletions listmonk/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
lst = '/api/lists/{list_id}'
subscriber = '/api/subscribers/{subscriber_id}'
subscribers = '/api/subscribers'
opt_in = '/subscription/optin/{subscriber_uuid}'
send_tx = '/api/tx'

0 comments on commit df7867c

Please sign in to comment.