summaryrefslogtreecommitdiffstats
path: root/ansible_collections/community/general/plugins/modules/bearychat.py
blob: 28f1f8fcd9b856b8f6b37e2e84dff90e8174bec3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright (c) 2016, Jiangge Zhang <tonyseek@gmail.com>
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later

from __future__ import absolute_import, division, print_function
__metaclass__ = type

DOCUMENTATION = '''
module: bearychat
short_description: Send BearyChat notifications
description:
    - The M(community.general.bearychat) module sends notifications to U(https://bearychat.com)
      via the Incoming Robot integration.
author: "Jiangge Zhang (@tonyseek)"
extends_documentation_fragment:
  - community.general.attributes
attributes:
  check_mode:
    support: none
  diff_mode:
    support: none
options:
  url:
    type: str
    description:
      - BearyChat WebHook URL. This authenticates you to the bearychat
        service. It looks like
        C(https://hook.bearychat.com/=ae2CF/incoming/e61bd5c57b164e04b11ac02e66f47f60).
    required: true
  text:
    type: str
    description:
      - Message to send.
  markdown:
    description:
      - If C(true), text will be parsed as markdown.
    default: true
    type: bool
  channel:
    type: str
    description:
      - Channel to send the message to. If absent, the message goes to the
        default channel selected by the I(url).
  attachments:
    type: list
    elements: dict
    description:
      - Define a list of attachments. For more information, see
        https://github.com/bearyinnovative/bearychat-tutorial/blob/master/robots/incoming.md#attachments
'''

EXAMPLES = """
- name: Send notification message via BearyChat
  local_action:
    module: bearychat
    url: |
      https://hook.bearychat.com/=ae2CF/incoming/e61bd5c57b164e04b11ac02e66f47f60
    text: "{{ inventory_hostname }} completed"

- name: Send notification message via BearyChat all options
  local_action:
    module: bearychat
    url: |
      https://hook.bearychat.com/=ae2CF/incoming/e61bd5c57b164e04b11ac02e66f47f60
    text: "{{ inventory_hostname }} completed"
    markdown: false
    channel: "#ansible"
    attachments:
      - title: "Ansible on {{ inventory_hostname }}"
        text: "May the Force be with you."
        color: "#ffffff"
        images:
          - http://example.com/index.png
"""

RETURN = """
msg:
    description: execution result
    returned: success
    type: str
    sample: "OK"
"""

try:
    from ansible.module_utils.six.moves.urllib.parse import urlparse, urlunparse
    HAS_URLPARSE = True
except Exception:
    HAS_URLPARSE = False
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.urls import fetch_url


def build_payload_for_bearychat(module, text, markdown, channel, attachments):
    payload = {}
    if text is not None:
        payload['text'] = text
    if markdown is not None:
        payload['markdown'] = markdown
    if channel is not None:
        payload['channel'] = channel
    if attachments is not None:
        payload.setdefault('attachments', []).extend(
            build_payload_for_bearychat_attachment(
                module, item.get('title'), item.get('text'), item.get('color'),
                item.get('images'))
            for item in attachments)
    payload = 'payload=%s' % module.jsonify(payload)
    return payload


def build_payload_for_bearychat_attachment(module, title, text, color, images):
    attachment = {}
    if title is not None:
        attachment['title'] = title
    if text is not None:
        attachment['text'] = text
    if color is not None:
        attachment['color'] = color
    if images is not None:
        target_images = attachment.setdefault('images', [])
        if not isinstance(images, (list, tuple)):
            images = [images]
        for image in images:
            if isinstance(image, dict) and 'url' in image:
                image = {'url': image['url']}
            elif hasattr(image, 'startswith') and image.startswith('http'):
                image = {'url': image}
            else:
                module.fail_json(
                    msg="BearyChat doesn't have support for this kind of "
                        "attachment image")
            target_images.append(image)
    return attachment


def do_notify_bearychat(module, url, payload):
    response, info = fetch_url(module, url, data=payload)
    if info['status'] != 200:
        url_info = urlparse(url)
        obscured_incoming_webhook = urlunparse(
            (url_info.scheme, url_info.netloc, '[obscured]', '', '', ''))
        module.fail_json(
            msg=" failed to send %s to %s: %s" % (
                payload, obscured_incoming_webhook, info['msg']))


def main():
    module = AnsibleModule(argument_spec={
        'url': dict(type='str', required=True, no_log=True),
        'text': dict(type='str'),
        'markdown': dict(default=True, type='bool'),
        'channel': dict(type='str'),
        'attachments': dict(type='list', elements='dict'),
    })

    if not HAS_URLPARSE:
        module.fail_json(msg='urlparse is not installed')

    url = module.params['url']
    text = module.params['text']
    markdown = module.params['markdown']
    channel = module.params['channel']
    attachments = module.params['attachments']

    payload = build_payload_for_bearychat(
        module, text, markdown, channel, attachments)
    do_notify_bearychat(module, url, payload)

    module.exit_json(msg="OK")


if __name__ == '__main__':
    main()