Compare commits
5 Commits
v2.1.8-bet
...
v2.1.9
Author | SHA1 | Date | |
---|---|---|---|
![]() |
8e4aba7ed4 | ||
![]() |
8c0ef75d4c | ||
![]() |
76c4b3bb71 | ||
![]() |
112b1c7984 | ||
![]() |
c22a2513e3 |
@@ -1,5 +1,11 @@
|
||||
# Changelog
|
||||
|
||||
## v2.1.9 (2018-05-21)
|
||||
|
||||
* Notifications:
|
||||
* New: Added "live" to notification parameters.
|
||||
|
||||
|
||||
## v2.1.8-beta (2018-05-19)
|
||||
|
||||
* Newsletters:
|
||||
|
@@ -4,12 +4,12 @@
|
||||
If you think you can contribute code to the Tautulli repository, do not hesitate to submit a pull request.
|
||||
|
||||
### Branches
|
||||
All pull requests should be based on the `dev` branch, to minimize cross merges. When you want to develop a new feature, clone the repository with `git clone origin/dev -b FEATURE_NAME`. Use meaningful commit messages.
|
||||
All pull requests should be based on the `nightly` branch, to minimize cross merges. When you want to develop a new feature, clone the repository with `git clone origin/nightly -b FEATURE_NAME`. Use meaningful commit messages.
|
||||
|
||||
### Python Code
|
||||
|
||||
#### Compatibility
|
||||
The code should work with Python 2.7. Note that Tautulli runs on different platforms, including Network Attached Storage devices such as Synology.
|
||||
The code should work with Python 2.7. Note that Tautulli runs on many different platforms.
|
||||
|
||||
Re-use existing code. Do not hesitate to add logging in your code. You can the logger module `plexpy.logger.*` for this. Web requests are invoked via `plexpy.request.*` and derived ones. Use these methods to automatically add proper and meaningful error handling.
|
||||
|
||||
@@ -29,13 +29,10 @@ Although Tautulli did not adapt a code convention in the past, we try to follow
|
||||
#### Documentation
|
||||
Document your code. Use docstrings See [PEP-257](https://www.python.org/dev/peps/pep-0257/) for more information.
|
||||
|
||||
#### Continuous Integration
|
||||
Tautulli has a configuration file for [travis-ci](https://travis-ci.org/). You can add your forked repo to Travis to have it check your code against PEP8, PyLint, and PyFlakes for you. Your pull request will show a green check mark or a red cross on each tested commit, depending on if linting passes.
|
||||
|
||||
### HTML/Template code
|
||||
|
||||
#### Compatibility
|
||||
HTML5 compatible browsers are targetted. There is no specific mobile version of Tautulli yet.
|
||||
HTML5 compatible browsers are targeted.
|
||||
|
||||
#### Conventions
|
||||
* 4 space indentation
|
||||
|
@@ -2935,6 +2935,7 @@ a .home-platforms-list-cover-face:hover
|
||||
}
|
||||
.stacked-configs > li > span > a.toggle-left,
|
||||
.stacked-configs > li > span > span.toggle-left {
|
||||
float: left;
|
||||
color: #444;
|
||||
padding-right: 8px;
|
||||
}
|
||||
@@ -2945,16 +2946,6 @@ a .home-platforms-list-cover-face:hover
|
||||
.stacked-configs > li > span > span.active {
|
||||
color: #f9be03;
|
||||
}
|
||||
.stacked-configs > li.new-notification-agent,
|
||||
.stacked-configs > li.notification-agent,
|
||||
.stacked-configs > li.add-notification-agent,
|
||||
.stacked-configs > li.new-newsletter-agent,
|
||||
.stacked-configs > li.newsletter-agent,
|
||||
.stacked-configs > li.add-newsletter-agent,
|
||||
.stacked-configs > li.mobile-device,
|
||||
.stacked-configs > li.add-mobile-device {
|
||||
cursor: pointer;
|
||||
}
|
||||
.stacked-configs > li.mobile-device > span > a.toggle-left,
|
||||
.stacked-configs > li.mobile-device > span > span.toggle-left {
|
||||
color: #999;
|
||||
@@ -4102,3 +4093,6 @@ a[data-tab-destination] {
|
||||
margin: 0 auto 50px auto;
|
||||
text-align: center;
|
||||
}
|
||||
.pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
@@ -11,12 +11,11 @@ DOCUMENTATION :: END
|
||||
|
||||
<ul class="stacked-configs list-unstyled">
|
||||
% for device in sorted(devices_list, key=lambda k: k['device_name']):
|
||||
<li class="mobile-device" data-id="${device['id']}" data-name="${device['device_name']}">
|
||||
<li class="mobile-device pointer" data-id="${device['id']}" data-name="${device['device_name']}">
|
||||
<span>
|
||||
<!--<span class="toggle-right mobile-device-tooltip edit-mobile-device" data-toggle="tooltip" data-placement="top" title="Edit Device"><i class="fa fa-lg fa-pencil"></i></span>-->
|
||||
<span class="toggle-left"><i class="fa fa-lg fa-mobile"></i></span>
|
||||
<span class="toggle-left"><i class="fa fa-lg fa-fw fa-mobile"></i></span>
|
||||
${device['friendly_name'] or device['device_name']} <span class="friendly_name">(${device['id']})</span>
|
||||
<span class="toggle-right"><i class="fa fa-lg fa-cog"></i></span>
|
||||
<span class="toggle-right"><i class="fa fa-lg fa-fw fa-cog"></i></span>
|
||||
<span class="toggle-right friendly_name" id="device-last_seen-${device['id']}">
|
||||
% if device['last_seen']:
|
||||
<script>
|
||||
@@ -26,14 +25,13 @@ DOCUMENTATION :: END
|
||||
never
|
||||
% endif
|
||||
</span>
|
||||
<!--<span class="toggle-right delete-mobile-device" data-toggle="tooltip" data-placement="top" title="Remove Device"><i class="fa fa-lg fa-times"></i></span>-->
|
||||
</span>
|
||||
</li>
|
||||
% endfor
|
||||
<li class="add-mobile-device" id="register-mobile-device" data-target="#api-qr-modal" data-toggle="modal">
|
||||
<li class="add-mobile-device pointer" id="register-mobile-device" data-target="#api-qr-modal" data-toggle="modal">
|
||||
<span>
|
||||
<span class="toggle-left"><i class="fa fa-lg fa-mobile"></i></span> Register a new device
|
||||
<span class="toggle-right"><i class="fa fa-lg fa-plus"></i></span>
|
||||
<span class="toggle-left"><i class="fa fa-lg fa-fw fa-mobile"></i></span> Register a new device
|
||||
<span class="toggle-right"><i class="fa fa-lg fa-fw fa-plus"></i></span>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
@@ -12,15 +12,15 @@ DOCUMENTATION :: END
|
||||
<% from plexpy.newsletter_handler import NEWSLETTER_SCHED %>
|
||||
<ul class="stacked-configs list-unstyled">
|
||||
% for newsletter in sorted(newsletters_list, key=lambda k: (k['agent_label'], k['friendly_name'], k['id'])):
|
||||
<li class="newsletter-agent" data-id="${newsletter['id']}">
|
||||
<li class="newsletter-agent pointer" data-id="${newsletter['id']}">
|
||||
<span>
|
||||
<span class="toggle-left trigger-tooltip ${'active' if newsletter['active'] else ''}" data-toggle="tooltip" data-placement="top" title="Newsletter ${'active' if newsletter['active'] else 'inactive'}"><i class="fa fa-lg fa-newspaper-o"></i></span>
|
||||
<span class="toggle-left trigger-tooltip ${'active' if newsletter['active'] else ''}" data-toggle="tooltip" data-placement="top" title="Newsletter ${'active' if newsletter['active'] else 'inactive'}"><i class="fa fa-lg fa-fw fa-newspaper-o"></i></span>
|
||||
% if newsletter['friendly_name']:
|
||||
${newsletter['agent_label']} <span class="friendly_name">(${newsletter['id']} - ${newsletter['friendly_name']})</span>
|
||||
% else:
|
||||
${newsletter['agent_label']} <span class="friendly_name">(${newsletter['id']})</span>
|
||||
% endif
|
||||
<span class="toggle-right"><i class="fa fa-lg fa-cog"></i></span>
|
||||
<span class="toggle-right"><i class="fa fa-lg fa-fw fa-cog"></i></span>
|
||||
<span class="toggle-right friendly_name" id="newsletter-next_run-${newsletter['id']}">
|
||||
% if NEWSLETTER_SCHED.get_job('newsletter-{}'.format(newsletter['id'])):
|
||||
<% job = NEWSLETTER_SCHED.get_job('newsletter-{}'.format(newsletter['id'])) %>
|
||||
@@ -32,10 +32,10 @@ DOCUMENTATION :: END
|
||||
</span>
|
||||
</li>
|
||||
% endfor
|
||||
<li class="add-newsletter-agent" id="add-newsletter-agent" data-target="#add-newsletter-modal" data-toggle="modal">
|
||||
<li class="add-newsletter-agent pointer" id="add-newsletter-agent" data-target="#add-newsletter-modal" data-toggle="modal">
|
||||
<span>
|
||||
<span class="toggle-left"><i class="fa fa-lg fa-newspaper-o"></i></span> Add a new newsletter agent
|
||||
<span class="toggle-right"><i class="fa fa-lg fa-plus"></i></span>
|
||||
<span class="toggle-left"><i class="fa fa-lg fa-fw fa-newspaper-o"></i></span> Add a new newsletter agent
|
||||
<span class="toggle-right"><i class="fa fa-lg fa-fw fa-plus"></i></span>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
@@ -1,7 +1,8 @@
|
||||
% if notifier:
|
||||
<%!
|
||||
import json
|
||||
from plexpy import helpers, notifiers, users
|
||||
from plexpy import notifiers, users
|
||||
from plexpy.helpers import checked
|
||||
available_notification_actions = notifiers.available_notification_actions()
|
||||
|
||||
user_emails = [{'user': u['friendly_name'] or u['username'], 'email': u['email']} for u in users.Users().get_users() if u['email']]
|
||||
@@ -70,7 +71,7 @@
|
||||
% elif item['input_type'] == 'checkbox':
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" data-id="${item['name']}" class="checkboxes" value="1" ${helpers.checked(item['value'])}> ${item['label']}
|
||||
<input type="checkbox" data-id="${item['name']}" class="checkboxes" value="1" ${checked(item['value'])}> ${item['label']}
|
||||
</label>
|
||||
<p class="help-block">${item['description'] | n}</p>
|
||||
<input type="hidden" id="${item['name']}" name="${item['name']}" value="${item['value']}">
|
||||
@@ -146,7 +147,7 @@
|
||||
% for action in available_notification_actions:
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" data-id="${action['name']}" class="checkboxes" value="1" ${helpers.checked(notifier['actions'][action['name']])}> ${action['label']}
|
||||
<input type="checkbox" data-id="${action['name']}" class="checkboxes" value="1" ${checked(notifier['actions'][action['name']])}> ${action['label']}
|
||||
</label>
|
||||
<p class="help-block">${action['description'] | n}</p>
|
||||
<input type="hidden" id="${action['name']}" name="${action['name']}" value="${notifier['actions'][action['name']]}">
|
||||
|
@@ -11,22 +11,22 @@ DOCUMENTATION :: END
|
||||
|
||||
<ul class="stacked-configs list-unstyled">
|
||||
% for notifier in sorted(notifiers_list, key=lambda k: (k['agent_label'].lower(), k['friendly_name'], k['id'])):
|
||||
<li class="notification-agent" data-id="${notifier['id']}">
|
||||
<li class="notification-agent pointer" data-id="${notifier['id']}">
|
||||
<span>
|
||||
<span class="toggle-left trigger-tooltip ${'active' if notifier['active'] else ''}" data-toggle="tooltip" data-placement="top" title="Triggers ${'active' if notifier['active'] else 'inactive'}"><i class="fa fa-lg fa-bell"></i></span>
|
||||
<span class="toggle-left trigger-tooltip ${'active' if notifier['active'] else ''}" data-toggle="tooltip" data-placement="top" title="Triggers ${'active' if notifier['active'] else 'inactive'}"><i class="fa fa-lg fa-fw fa-bell"></i></span>
|
||||
% if notifier['friendly_name']:
|
||||
${notifier['agent_label']} <span class="friendly_name">(${notifier['id']} - ${notifier['friendly_name']})</span>
|
||||
% else:
|
||||
${notifier['agent_label']} <span class="friendly_name">(${notifier['id']})</span>
|
||||
% endif
|
||||
<span class="toggle-right"><i class="fa fa-lg fa-cog"></i></span>
|
||||
<span class="toggle-right"><i class="fa fa-lg fa-fw fa-cog"></i></span>
|
||||
</span>
|
||||
</li>
|
||||
% endfor
|
||||
<li class="add-notification-agent" id="add-notification-agent" data-target="#add-notifier-modal" data-toggle="modal">
|
||||
<li class="add-notification-agent pointer" id="add-notification-agent" data-target="#add-notifier-modal" data-toggle="modal">
|
||||
<span>
|
||||
<span class="toggle-left"><i class="fa fa-lg fa-bell"></i></span> Add a new notification agent
|
||||
<span class="toggle-right"><i class="fa fa-lg fa-plus"></i></span>
|
||||
<span class="toggle-left"><i class="fa fa-lg fa-fw fa-bell"></i></span> Add a new notification agent
|
||||
<span class="toggle-right"><i class="fa fa-lg fa-fw fa-plus"></i></span>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
@@ -650,7 +650,7 @@
|
||||
</div>
|
||||
|
||||
<div class="form-group has-feedback" id="pms_ip_group">
|
||||
<label for="pms_ip">Plex IP or Hostname</label>
|
||||
<label for="pms_ip">Plex IP Address or Hostname</label>
|
||||
<div class="row">
|
||||
<div class="col-md-9" id="selectize-pms-ip-container">
|
||||
<div class="input-group">
|
||||
@@ -1423,7 +1423,7 @@
|
||||
<div class="col-md-12">
|
||||
<ul class="stacked-configs list-unstyled">
|
||||
% for agent in sorted(available_notification_agents, key=lambda k: k['label'].lower()):
|
||||
<li class="new-notification-agent" data-id="${agent['id']}">
|
||||
<li class="new-notification-agent pointer" data-id="${agent['id']}">
|
||||
<span>${agent['label']}</span>
|
||||
</li>
|
||||
% endfor
|
||||
@@ -1451,7 +1451,7 @@
|
||||
<div class="col-md-12">
|
||||
<ul class="stacked-configs list-unstyled">
|
||||
% for agent in available_newsletter_agents:
|
||||
<li class="new-newsletter-agent" data-id="${agent['id']}">
|
||||
<li class="new-newsletter-agent pointer" data-id="${agent['id']}">
|
||||
<span>${agent['label']}</span>
|
||||
</li>
|
||||
% endfor
|
||||
@@ -1793,6 +1793,7 @@
|
||||
}
|
||||
|
||||
function loadNotifierConfig(notifier_id) {
|
||||
showMsg('<i class="fa fa-refresh fa-spin"></i> Loading Configuration', false);
|
||||
$.ajax({
|
||||
url: 'get_notifier_config_modal',
|
||||
data: { notifier_id: notifier_id },
|
||||
@@ -1800,6 +1801,7 @@
|
||||
async: true,
|
||||
complete: function (xhr, status) {
|
||||
$("#notifier-config-modal").html(xhr.responseText).modal('show');
|
||||
showMsg('<i class="fa fa-check"></i> Configuration Loaded', false, true, 2000);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1816,6 +1818,7 @@
|
||||
}
|
||||
|
||||
function loadNewsletterConfig(newsletter_id) {
|
||||
showMsg('<i class="fa fa-refresh fa-spin"></i> Loading Configuration', false);
|
||||
$.ajax({
|
||||
url: 'get_newsletter_config_modal',
|
||||
data: { newsletter_id: newsletter_id },
|
||||
@@ -1823,6 +1826,7 @@
|
||||
async: true,
|
||||
complete: function (xhr, status) {
|
||||
$("#newsletter-config-modal").html(xhr.responseText).modal('show');
|
||||
showMsg('<i class="fa fa-check"></i> Configuration Loaded', false, true, 2000);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1839,6 +1843,7 @@
|
||||
}
|
||||
|
||||
function loadMobileDeviceConfig(mobile_device_id) {
|
||||
showMsg('<i class="fa fa-refresh fa-spin"></i> Loading Configuration', false);
|
||||
$.ajax({
|
||||
url: 'get_mobile_device_config_modal',
|
||||
data: { mobile_device_id: mobile_device_id },
|
||||
@@ -1846,6 +1851,7 @@
|
||||
async: true,
|
||||
complete: function (xhr, status) {
|
||||
$("#mobile-device-config-modal").html(xhr.responseText).modal('show');
|
||||
showMsg('<i class="fa fa-check"></i> Configuration Loaded', false, true, 2000);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -2591,7 +2597,7 @@ $(document).ready(function() {
|
||||
var result = $.parseJSON(xhr.responseText);
|
||||
var msg = result.message;
|
||||
$('#add-notifier-modal').modal('hide');
|
||||
if (result.result == 'success') {
|
||||
if (result.result === 'success') {
|
||||
showMsg('<i class="fa fa-check"></i> ' + msg, false, true, 5000);
|
||||
loadNotifierConfig(result.notifier_id);
|
||||
} else {
|
||||
@@ -2613,7 +2619,7 @@ $(document).ready(function() {
|
||||
var result = $.parseJSON(xhr.responseText);
|
||||
var msg = result.message;
|
||||
$('#add-newsletter-modal').modal('hide');
|
||||
if (result.result == 'success') {
|
||||
if (result.result === 'success') {
|
||||
showMsg('<i class="fa fa-check"></i> ' + msg, false, true, 5000);
|
||||
loadNewsletterConfig(result.newsletter_id);
|
||||
} else {
|
||||
|
@@ -339,6 +339,7 @@ NOTIFICATION_PARAMETERS = [
|
||||
{'name': 'Optimized Version', 'type': 'int', 'value': 'optimized_version', 'description': 'If the stream is an optimized version.', 'example': '0 or 1'},
|
||||
{'name': 'Optimized Version Profile', 'type': 'str', 'value': 'optimized_version_profile', 'description': 'The optimized version profile of the stream.'},
|
||||
{'name': 'Synced Version', 'type': 'int', 'value': 'synced_version', 'description': 'If the stream is an synced version.', 'example': '0 or 1'},
|
||||
{'name': 'Live', 'type': 'int', 'value': 'live', 'description': 'If the stream is live TV.', 'example': '0 or 1'},
|
||||
{'name': 'Stream Local', 'type': 'int', 'value': 'stream_local', 'description': 'If the stream is local.', 'example': '0 or 1'},
|
||||
{'name': 'Stream Location', 'type': 'str', 'value': 'stream_location', 'description': 'The network location of the stream.', 'example': 'lan or wan'},
|
||||
{'name': 'Stream Bandwidth', 'type': 'int', 'value': 'stream_bandwidth', 'description': 'The required bandwidth (in kbps) of the stream.', 'help_text': 'not the used bandwidth'},
|
||||
|
@@ -206,7 +206,7 @@ def set_newsletter_config(newsletter_id=None, agent_id=None, **kwargs):
|
||||
if str(agent_id).isdigit():
|
||||
agent_id = int(agent_id)
|
||||
else:
|
||||
logger.error(u"Tautulli Newsletters :: Unable to set exisiting newsletter: invalid agent_id %s."
|
||||
logger.error(u"Tautulli Newsletters :: Unable to set existing newsletter: invalid agent_id %s."
|
||||
% agent_id)
|
||||
return False
|
||||
|
||||
|
@@ -509,7 +509,7 @@ def add_notifier_config(agent_id=None, **kwargs):
|
||||
'agent_name': agent['name'],
|
||||
'agent_label': agent['label'],
|
||||
'friendly_name': '',
|
||||
'notifier_config': json.dumps(get_agent_class(agent_id=agent['id']).config),
|
||||
'notifier_config': json.dumps(agent_class.config),
|
||||
'custom_conditions': json.dumps(DEFAULT_CUSTOM_CONDITIONS),
|
||||
'custom_conditions_logic': ''
|
||||
}
|
||||
@@ -540,7 +540,7 @@ def set_notifier_config(notifier_id=None, agent_id=None, **kwargs):
|
||||
if str(agent_id).isdigit():
|
||||
agent_id = int(agent_id)
|
||||
else:
|
||||
logger.error(u"Tautulli Notifiers :: Unable to set exisiting notifier: invalid agent_id %s."
|
||||
logger.error(u"Tautulli Notifiers :: Unable to set existing notifier: invalid agent_id %s."
|
||||
% agent_id)
|
||||
return False
|
||||
|
||||
@@ -570,7 +570,7 @@ def set_notifier_config(notifier_id=None, agent_id=None, **kwargs):
|
||||
'agent_name': agent['name'],
|
||||
'agent_label': agent['label'],
|
||||
'friendly_name': kwargs.get('friendly_name', ''),
|
||||
'notifier_config': json.dumps(notifier_config),
|
||||
'notifier_config': json.dumps(agent_class.config),
|
||||
'custom_conditions': kwargs.get('custom_conditions', json.dumps(DEFAULT_CUSTOM_CONDITIONS)),
|
||||
'custom_conditions_logic': kwargs.get('custom_conditions_logic', ''),
|
||||
}
|
||||
@@ -807,7 +807,7 @@ class Notifier(object):
|
||||
if response is not None and response.status_code >= 400 and response.status_code < 500:
|
||||
verify_msg = " Verify you notification agent settings are correct."
|
||||
|
||||
logger.error(u"Tautulli Notifiers :: {name} notification failed.{}".format(verify_msg, name=self.NAME))
|
||||
logger.error(u"Tautulli Notifiers :: {name} notification failed.{msg}".format(msg=verify_msg, name=self.NAME))
|
||||
|
||||
if err_msg:
|
||||
logger.error(u"Tautulli Notifiers :: {}".format(err_msg))
|
||||
|
@@ -1,2 +1,2 @@
|
||||
PLEXPY_BRANCH = "beta"
|
||||
PLEXPY_RELEASE_VERSION = "v2.1.8-beta"
|
||||
PLEXPY_BRANCH = "master"
|
||||
PLEXPY_RELEASE_VERSION = "v2.1.9"
|
||||
|
@@ -3222,7 +3222,7 @@ class WebInterface(object):
|
||||
@requireAuth(member_of("admin"))
|
||||
@addtoapi()
|
||||
def set_notifier_config(self, notifier_id=None, agent_id=None, **kwargs):
|
||||
""" Configure an exisitng notificaiton agent.
|
||||
""" Configure an existing notification agent.
|
||||
|
||||
```
|
||||
Required parameters:
|
||||
@@ -3341,10 +3341,10 @@ class WebInterface(object):
|
||||
return {'result': 'success', 'message': 'Notification queued.'}
|
||||
else:
|
||||
logger.debug(u"Unable to send %snotification, invalid notifier_id %s." % (test, notifier_id))
|
||||
return {'result': 'success', 'message': 'Invalid notifier id %s.' % notifier_id}
|
||||
return {'result': 'error', 'message': 'Invalid notifier id %s.' % notifier_id}
|
||||
else:
|
||||
logger.debug(u"Unable to send %snotification, no notifier_id received." % test)
|
||||
return {'result': 'success', 'message': 'No notifier id received.'}
|
||||
return {'result': 'error', 'message': 'No notifier id received.'}
|
||||
|
||||
@cherrypy.expose
|
||||
@cherrypy.tools.json_out()
|
||||
@@ -3481,7 +3481,7 @@ class WebInterface(object):
|
||||
@requireAuth(member_of("admin"))
|
||||
@addtoapi()
|
||||
def set_mobile_device_config(self, mobile_device_id=None, **kwargs):
|
||||
""" Configure an exisitng notificaiton agent.
|
||||
""" Configure an existing notification agent.
|
||||
|
||||
```
|
||||
Required parameters:
|
||||
@@ -5678,7 +5678,7 @@ class WebInterface(object):
|
||||
@requireAuth(member_of("admin"))
|
||||
@addtoapi()
|
||||
def set_newsletter_config(self, newsletter_id=None, agent_id=None, **kwargs):
|
||||
""" Configure an exisitng newsletter agent.
|
||||
""" Configure an existing newsletter agent.
|
||||
|
||||
```
|
||||
Required parameters:
|
||||
|
Reference in New Issue
Block a user