def __init__(self, token):
     self.api = WebexTeamsAPI(access_token=token)
Example #2
0
import argparse
from dotenv import load_dotenv, find_dotenv
import pandas as pd
import numpy as np
load_dotenv(find_dotenv())

from webexteamssdk import WebexTeamsAPI
api = WebexTeamsAPI()

# Add arguments
parser = argparse.ArgumentParser(
    description='Specify a file and the number of people per group')
parser.add_argument('-n',
                    type=int,
                    help='an integer for size of each group',
                    required=True)
parser.add_argument('-f',
                    dest='file',
                    help='the CSV file with single column of email addresses',
                    required=True)
parser.add_argument('-t', dest='test', help='do a dry run?', required=False)
# Parse args
args = parser.parse_args()

# Store in CONST VARIABLE
N = args.n
M = 5
FILENAME = args.file
SPACE_TITLE = 'Holiday Chat Room'
OBSERVERS = ['*****@*****.**']  # list of observers
Example #3
0
import os
import argparse
import sys
from flask import Flask, request
from webexteamssdk import WebexTeamsAPI

__app__ = "cisco-dnac-platform-webex-notifications"
__version__ = "1.3.3"
__author__ = "Robert Csapo"
__email__ = "*****@*****.**"
__version__ = "1.0"
__copyright__ = "Copyright (c) 2020 Cisco and/or its affiliates."
__license__ = "Cisco Sample Code License, Version 1.1"
""" Read Cisco Webex Teams Settings either for Environment or in Code """
if "WEBEX_TEAMS_ACCESS_TOKEN" not in os.environ:
    webexAPI = WebexTeamsAPI(access_token="CHANGEME")
else:
    webexAPI = WebexTeamsAPI()

if "WEBEX_TEAMS_ROOM_ID" not in os.environ:
    os.environ["WEBEX_TEAMS_ROOM_ID"] = "CHANGEME"
    webexRoomId = os.environ["WEBEX_TEAMS_ROOM_ID"]
else:
    webexRoomId = os.environ["WEBEX_TEAMS_ROOM_ID"]
""" Verify Cisco Webex Teams Settings """


def webex_init_healthcheck():
    results = {}
    try:
        bot = webexAPI.people.me()
Example #4
0
 def __init__(self, access_token: Optional[Text], room: Optional[Text]) -> None:
     self.room = room
     self.api = WebexTeamsAPI(access_token)
Example #5
0
 def __init__(self, access_token, room):
     self.room = room
     self.api = WebexTeamsAPI(access_token)
from webexteamssdk import WebexTeamsAPI
'''
CREATES a room on webexteams
DELETE ALL PREVIOUS ROOMS
ADD user to the room
'''
message = "**I am an IT-Professional, and I have completed this challenge!!!**"

api = WebexTeamsAPI(
    access_token=
    "ZmNmMDA5ZmYtNmNjNy00YTBlLThkMzUtMDg4YjhiMzJlYmFlNzUwMDFkYTctMzRj_PF84_consumer"
)

#Deletes previous rooms where i belong
mem = api.memberships.list()
for m in mem:
    print(m)
    api.rooms.delete(roomId=m.roomId)

room = api.rooms.create(title="ROOM created with SDK2")

api.messages.create(roomId=room.id, text=message)

#Invites Ariel bot

api.memberships.create(roomId=room.id, personEmail="*****@*****.**")
Example #7
0
    def __init__(
        self,
        teams_bot_name,
        teams_bot_token=None,
        teams_api_url=None,
        teams_bot_email=None,
        teams_bot_url=None,
        default_action="/help",
        webhook_resource_event=None,
        webhook_resource="messages",
        webhook_event="created",
        approved_users=[],
        debug=False,
    ):
        """
        Initialize a new TeamsBot

        :param teams_bot_name: Friendly name for this Bot (webhook name)
        :param teams_bot_token: Teams Auth Token for Bot Account
        :param teams_api_url: URL to the Teams/Webex API endpoint
        :param teams_bot_email: Teams Bot Email Address
        :param teams_bot_url: WebHook URL for this Bot
        :param default_action: What action to take if no command found.
                Defaults to /help
        :param webhook_resource: What resource to trigger webhook on
                Defaults to messages
        :param webhook_event: What resource event to trigger webhook on
                Defaults to created
        :param webhook_resource_event: List of dicts for which resource/events
                to create webhooks for.
                [{"resource": "messages", "event": "created"},
                {"resource": "attachmentActions", "event": "created"}]
        :param approved_users: List of approved users (by email) to interact with bot. Default all users.
        :param debug: boolean value for debut messages
        """

        super(TeamsBot, self).__init__(teams_bot_name)

        # Verify required parameters provided
        if None in (
                teams_bot_name,
                teams_bot_token,
                teams_bot_email,
                teams_bot_token,
        ):
            raise ValueError("TeamsBot requires teams_bot_name, "
                             "teams_bot_token, teams_bot_email, teams_bot_url")

        self.DEBUG = debug
        self.teams_bot_name = teams_bot_name
        self.teams_bot_token = teams_bot_token
        self.teams_bot_email = teams_bot_email
        self.teams_bot_url = teams_bot_url
        self.default_action = default_action
        self.approved_users = approved_users
        self.webhook_resource = webhook_resource
        self.webhook_event = webhook_event
        self.webhook_resource_event = webhook_resource_event

        # Create Teams API Object for interacting with Teams
        if teams_api_url:
            self.teams = WebexTeamsAPI(access_token=teams_bot_token,
                                       base_url=teams_api_url)
        else:
            self.teams = WebexTeamsAPI(access_token=teams_bot_token)

        # A dictionary of commands this bot listens to
        # Each key in the dictionary is a command, with associated help
        # text and callback function
        # By default supports 2 command, /echo and /help
        self.commands = {
            "/echo": {
                "help": "Reply back with the same message sent.",
                "callback": self.send_echo,
            },
            "/help": {
                "help": "Get help.",
                "callback": self.send_help
            },
        }

        # Set default help message
        self.help_message = "Hello!  I understand the following commands:  \n"

        # Flask Application URLs
        # Basic Health Check for Flask Application
        self.add_url_rule("/health", "health", self.health)
        # Endpoint to enable dynamically configuring account
        self.add_url_rule("/config", "config", self.config_bot)
        # Teams WebHook Target
        self.add_url_rule("/",
                          "index",
                          self.process_incoming_message,
                          methods=["POST"])

        # Setup the Teams WebHook and connections.
        self.teams_setup()
Example #8
0
Redis_TAC = redis.StrictRedis(connection_pool=Redis_TAC_Pool)
Redis_DB = Redis_HTTS

#CSOne GCI Authentication/Cookie Initialization
CSOneSession = CommonLib.CSOneSession(logger=CommonLib.HTTSLogger(
    name="GetGCI",
    logfile="GetGCI-HTTS-App.log",
    logfilepath=config['Logging']['LoggingPath']),
                                      debug=True)

#WebexTeams Initialization
sydney_local_timezone = timezone('Australia/Sydney')
isSentToSydneyHTTS = False
isSentToCBATeam = False
wbx_max_chr = 500
webexteamsapi_htts = WebexTeamsAPI(
    access_token=config['WebexTeams']['bot_token_htts'])
wbx_markdown_hyperlinks = "{}([eportal](https://eportal.cisco.com/#/public/account/{}/gr/overall)), SR [{}](http://mwz.cisco.com/{}), "
InQueueMinuteAlert = {
    '1': [int(min) for min in config['Case']['P1_Alert_Minute'].split(',')],
    '2': [int(min) for min in config['Case']['P2_Alert_Minute'].split(',')],
    '3': [int(min) for min in config['Case']['P3_Alert_Minute'].split(',')],
    '4': [int(min) for min in config['Case']['P4_Alert_Minute'].split(',')],
}

PollingTime = int(config['Redis']['PollingTime'])
CaseProcessedState = {}

print("================================")
print("Polling Time:{} seconds.".format(PollingTime))
print("Redis IP {} Port {} DB {}".format(config['Redis']['ServerIP'],
                                         config['Redis']['ServerPort'],
Example #9
0
from webexteamssdk import WebexTeamsAPI
import settings

api = WebexTeamsAPI(access_token=settings.teams_token)


def get_me():
    return api.people.me()


def send_message_to_user(user_id, message):
    toEmail = user_id + '@cisco.com'
    api.messages.create(toPersonEmail=toEmail, markdown=message)
    return


def send_message_to_room(room_id, message):
    api.messages.create(roomId=room_id, markdown=message)
    return


def _wrap(card_obj):
    return {
        "contentType": "application/vnd.microsoft.card.adaptive",
        "content": card_obj.to_dict()
    }


def send_card_to_user(user_id,
                      card_obj,
                      fallback_message='card creation failed'):
# Response has no content => delete only needs a return code 204
# HTTP Status 204 (No Content) indicates that the server has successfully fulfilled
# the request and that there is no content to send in the response payload body.

# In[ ]:

# STEP 13
# TO DO => Delete space from Webex
#####

# In[52]:

#####
# ALTERNATIVE: using WebexTeams SDK instead of HTTP Request
##### pip install webexteamssdk
from webexteamssdk import WebexTeamsAPI

# Variable which holds the message
msg = "Testing: message sent to Webex SDK ** IT Infrastructure Team **"

# New instance of the CiscoSparkAPI object
api = WebexTeamsAPI(access_token=current_access_token)

# Create a room and assign returned value to a variable
room = api.rooms.create("Webex SDK IT Infrastructure Team")

# Send message to specified room with markdown syntax.
send_msg = api.messages.create(roomId=room.id, markdown=msg)

##### View the result in Webex Teams
Example #11
0
def main():
    """Main program
    """
    # User input flags definition:
    parser = argparse.ArgumentParser(
        description="Sync IPAM server from DNA Center, DHCP server \
        and/or static hosts in CSV file. If no arguments are passed, the default is to sync \
        from all 3 sources.")
    parser.add_argument("-c",
                        "--dnac",
                        action="store_true",
                        help="sync IPAM from DNA Center")
    parser.add_argument("-d",
                        "--dhcp",
                        action="store_true",
                        help="sync IPAM from MS DHCP Server")
    parser.add_argument("-s",
                        "--static",
                        action="store_true",
                        help="sync IPAM from static CSV file")
    parser.add_argument("-v",
                        "--verify",
                        action="store_true",
                        help="verify the current IPAM subnet usage")
    parser.add_argument("-l",
                        metavar='IP-Address',
                        type=str,
                        help="search for an IP address inside IPAM")
    parser.add_argument(
        "-t",
        metavar='rerun-timer',
        type=int,
        help=
        "define the script auto-rerun timer in minutes. Default is 15; Minimum allowed is 5"
    )
    args = parser.parse_args()

    requests.packages.urllib3.disable_warnings()

    # Get the current time. First one is used to tag addresses inserted/refreshed
    # Second one is used to print logging timestamp:
    time_tag = int(time.time())
    time_now = time.asctime(time.localtime(time.time()))

    # Open a log file in local directory in append mode to write the log messages into,
    # and include the current day date (YYYY-MM-DD) in the filename:
    file_name = "logfile-phpipam_sync_%s.log" % datetime.now().strftime(
        "%Y-%m-%d")
    log_file = open(file_name, "a")
    log_file.write("\n\n**** Execution of PHPIPAM Sync Script on: %s ****\n" %
                   time_now)

    # File open to write email log notifications if any:
    email_body = open(EMAIL_CONTENT_FILE, "w")

    # Initiate the Webex Teams API session:
    webex_teams_api = WebexTeamsAPI(access_token=TEAMS_BOT_TOKEN)

    # Authenticate/refresh the token to IPAM:
    ipam_token = ipam_get_auth_token()["token"]

    # Create the API URI for IPAM addresses (hosts):
    ipam_addresses_url = ipam_create_url("addresses")

    # default rerun timer:
    script_rerun_timer = 15

    # If -c/--dnac input flag is set:
    if args.dnac:
        # Sync from DNAC to the IPAM DB:
        sync_from_dnac(time_tag, ipam_token, ipam_addresses_url, log_file,
                       webex_teams_api)
        # Delete the stale dnac hosts from IPAM DB:
        delete_stale_hosts(TAG_DNAC, time_tag, ipam_token, ipam_addresses_url,
                           log_file, email_body, EMAIL_CONTENT_FILE,
                           webex_teams_api)

    # If -d/--dhcp input flag is set:
    if args.dhcp:
        # Sync from the DHCP server scopes leases to the IPAM DB:
        sync_from_ms_dhcp_server(time_tag, ipam_token, ipam_addresses_url,
                                 log_file, EMAIL_CONTENT_FILE, webex_teams_api)
        # Delete the stale MS DHCP hosts from IPAM DB:
        delete_stale_hosts(TAG_MSDHCP, time_tag, ipam_token,
                           ipam_addresses_url, log_file, email_body,
                           EMAIL_CONTENT_FILE, webex_teams_api)
        # Sync from the IOS DHCP server:
        sync_from_ios_dhcp_server(time_tag, ipam_token, ipam_addresses_url,
                                  log_file, EMAIL_CONTENT_FILE,
                                  webex_teams_api)
        # Delete the stale IOS DHCP hosts from IPAM DB:
        delete_stale_hosts(TAG_IOSDHCP, time_tag, ipam_token,
                           ipam_addresses_url, log_file, email_body,
                           EMAIL_CONTENT_FILE, webex_teams_api)

    # If -s/--static input flag is set
    if args.static:
        # Sync the static hosts from the CSV file STATICS_CSV_FILE to the IPAM DB:
        sync_from_static_csv(STATICS_CSV_FILE, time_tag, ipam_token,
                             ipam_addresses_url, log_file, email_body,
                             EMAIL_CONTENT_FILE, webex_teams_api)
        # Delete the stale static hosts from IPAM DB:
        delete_stale_hosts(TAG_STATIC, time_tag, ipam_token,
                           ipam_addresses_url, log_file, email_body,
                           EMAIL_CONTENT_FILE, webex_teams_api)

    # If -v/--verify input flag is set:
    if args.verify:
        # Return the IPAM subnet usage:
        verify_ipam_subnet_usage(log_file, email_body, EMAIL_CONTENT_FILE)
        sys.exit(1)

    # If -l input flag is set:
    if args.l:
        # check if the argument entered is a valid IP address
        ip_address = args.l
        if not is_valid_ipv4_address(ip_address):
            print(
                "\nInvalid argument. Please enter a valid IP address after -l."
            )
            sys.exit(1)

        # Search for the IP address in IPAM DB:
        ipam_search_address_response = ipam_get_url(
            "addresses/search/%s/" % (ip_address), log_file,
            EMAIL_CONTENT_FILE)
        if ipam_search_address_response['success']:
            result = ipam_search_address_response["data"][0]
            print("\nIP address %s is present in IPAM Database:" % ip_address)
            column_names = "{0:20}{1:20}{2:50}{3:50}".format(
                "IP address", "MAC address", "Hostname", "Description")
            host_mac = "N/A" if result['mac'] is None else result['mac']
            host_hostname = "N/A" if result['hostname'] is None else result[
                'hostname']
            host_description = "N/A" if result[
                'description'] is None else result['description']
            column_values = "{0:20}{1:20}{2:50}{3:50}\n".format(
                ip_address, host_mac, host_hostname, host_description)
            print(column_names)
            print(column_values)
        else:
            print("\nIP address %s was not found in IPAM Database." %
                  ip_address)
        sys.exit(1)

    # If -t input flag is set:
    if args.t:
        # check if the argument entered is a valid integ
        timer_input = args.t

        # if input timer is less than 5 minutes, set the rerun_timer to 5 minutes and notify user:
        if timer_input < 5:
            print("\nThe input timer %s is too agressive. Setting to the minimum " \
                "recommended of 5 minutes." % args.t)
            timer_input = 5

        script_rerun_timer = timer_input

    # If no args are passed, or only the -t argument is passed:
    # Then sync from all the 3 sources and verify the IPAM subnet usage:
    if (len(sys.argv) == 1 or (args.t and len(sys.argv) == 3)):
        sync_from_dnac(time_tag, ipam_token, ipam_addresses_url, log_file,
                       webex_teams_api)
        delete_stale_hosts(TAG_DNAC, time_tag, ipam_token, ipam_addresses_url,
                           log_file, email_body, EMAIL_CONTENT_FILE,
                           webex_teams_api)
        sync_from_static_csv(STATICS_CSV_FILE, time_tag, ipam_token,
                             ipam_addresses_url, log_file, email_body,
                             EMAIL_CONTENT_FILE, webex_teams_api)
        delete_stale_hosts(TAG_STATIC, time_tag, ipam_token,
                           ipam_addresses_url, log_file, email_body,
                           EMAIL_CONTENT_FILE, webex_teams_api)
        sync_from_ms_dhcp_server(time_tag, ipam_token, ipam_addresses_url,
                                 log_file, EMAIL_CONTENT_FILE, webex_teams_api)
        delete_stale_hosts(TAG_MSDHCP, time_tag, ipam_token,
                           ipam_addresses_url, log_file, email_body,
                           EMAIL_CONTENT_FILE, webex_teams_api)
        sync_from_ios_dhcp_server(time_tag, ipam_token, ipam_addresses_url,
                                  log_file, EMAIL_CONTENT_FILE,
                                  webex_teams_api)
        delete_stale_hosts(TAG_IOSDHCP, time_tag, ipam_token,
                           ipam_addresses_url, log_file, email_body,
                           EMAIL_CONTENT_FILE, webex_teams_api)
        verify_ipam_subnet_usage(log_file, email_body, EMAIL_CONTENT_FILE)

    # close the open files, and send the email if email_flg is set:
    cleanup_before_exit(log_file, email_body, EMAIL_CONTENT_FILE)

    # Print message that the script will rerun in 15 minutes:
    print(
        "\n%s: The script will rerun in %s minutes. To exit press Ctrl-C...\n"
        % (time.asctime(time.localtime(time.time())), script_rerun_timer))
Example #12
0
new_cfg = f.readlines()
f.close

diff = compare_configs(old_cfg, new_cfg)
print(diff)

f = open('/bootflash/guest-share/CONFIG_FILES/diff', 'w')
f.write(diff)
f.close

if diff != '':
    # find the device hostname using RESTCONF
    device_name = cli('show run | inc hostname ').split()[1]
    print('Hostname: ' + device_name)
    # Initialize Webex Teams API
    api = WebexTeamsAPI(access_token=WEBEX_TEAMS_ACCESS_TOKEN, proxies=PROXY)
    bot = api.people.me()
    # Create a new space
    room = api.rooms.create(WEBEX_TEAMS_ROOM)
    # Add members to the space
    for WEBEX_TEAMS_MEMBER in WEBEX_TEAMS_MEMBERS:
        api.memberships.create(room.id, personEmail=WEBEX_TEAMS_MEMBER)
    # Send initial message
    api.messages.create(
        roomId=room.id,
        markdown=
        f"Hello <@all>,  \n# Configuration change detected!**  \nDevice hostname: **{device_name}**, detected the following changes made by user: **{user}**."
    )
    api.messages.create(roomId=room.id, text=diff)
    api.messages.create(
        roomId=room.id,
Example #13
0
import json
from flask import Flask, abort, request
from webexteamssdk import WebexTeamsAPI
import os
import requests
from dcUniConfig import config

BOT_ID = config.BOT_ID
ACCESS_TOKEN = config.ACCESS_TOKEN

with open('help_guide.json', 'r') as f:
    HELP_GUIDE = json.load(f)

app = Flask(__name__)
api = WebexTeamsAPI(ACCESS_TOKEN)

app.config['DEBUG'] = True
app.config['TEMPLATES_AUTO_RELOAD'] = True


def gitCommitMessage(commit):

    # send a message to the webex teams room with the details of the new commit

    compare = commit["compare"]
    committerMessage = commit["head_commit"]["message"]
    author = commit["head_commit"]["author"]["name"]
    committer = commit["head_commit"]["committer"]["name"]
    added = commit["head_commit"]["added"]
    removed = commit["head_commit"]["removed"]
Example #14
0
from webexteamssdk import WebexTeamsAPI

api = WebexTeamsAPI(
    access_token=
    'NDQ0ZTQ4ZTUtMDNhOC00MmE2LTgyZjYtNTUwODA4OTYwNDJlMDA2YzllMGQtY2Ew_PF84_1eb65fdf-9643-417f-9974-ad72cae0e10f'
)

teams = api.teams.list()

my_room_id = None

for team in teams:

    print('*' * 50)
    team_name = team.name
    team_id = team.id

    print(f"Team: {team_name}")

    rooms = api.rooms.list(team_id)
    for room in rooms:
        room_name = room.title
        room_id = room.id
        print(f"{'':>5}Room: {room_name}")
def main():
    """sync AD and WX Teams team membership"""
    with open(CONFIG_FILE, 'r') as config_file:
        config_params = yaml.full_load(config_file)

    wx_config = config_params['wxteams']
    wx_token = wx_config['auth_token']

    ldap_config = config_params['ldap']
    ldap_host = ldap_config['server']
    ldap_user = ldap_config['user']
    ldap_password = ldap_config['password']
    ldap_basedn = ldap_config['basedn']
    ldap_basedn_groups = ldap_config['basedn_groups']

    ldap_basedn_len = len(ldap_basedn)

    wx_teamquery = input('Please enter name of the team to examine: ')

    print('\nBuilding Webex Teams team list, please wait...', end='')
    api = WebexTeamsAPI(access_token=wx_token)
    wx_team_fulllist = list(api.teams.list(type='group'))
    print_done()

    # Populate list of query matches from full list, case insensitive
    wx_team_matchlist = [{'name': wx_team.name, 'id': wx_team.id}
                         for wx_team in wx_team_fulllist
                         if wx_teamquery.upper() in wx_team.name.upper()]


    if not wx_team_matchlist:
        bad_choice()

    # Finalize team list
    elif len(wx_team_matchlist) > 1:
        # multiple matches found, present user with choice
        for count, wx_team in enumerate(wx_team_matchlist, 1):
            print(f'{count}: {wx_team["name"]}')

        try:
            team_number = int(input('\nPlease enter number of team to compare: '))
        except ValueError:
            bad_choice()

        if team_number >= 0 and team_number < len(wx_team_matchlist)+1:
            team_number -= 1
        else:
            bad_choice()

    else:
        # one match found, use it
        team_number = 0

    # team selected
    if team_number >= 0:
        wx_team_match = {'name': wx_team_matchlist[team_number]['name'],
                         'id': wx_team_matchlist[team_number]['id']}

    else:
        bad_choice()

    # Catalogue team members
    if confirmed(f'Webex Teams \"{wx_team_match["name"]}\" team selected, are you sure?'):
        print(f'Gathering details on \"{wx_team_match["name"]}\" team...', end='')
        wx_team_members = list(api.team_memberships.list(teamId=wx_team_match['id']))
        print_done()
    else:
        bad_choice()


    ad_dl_query = input_with_default('Please enter name of AD DL to compare against: ',
                                     wx_teamquery)

    # Open LDAP connection to Active Directory
    print(f'Connecting to AD...', end='')
    server = ldap3.Server(ldap_host, use_ssl=True)
    connection = ldap3.Connection(server,
                                  user=ldap_user,
                                  password=ldap_password,
                                  authentication=ldap3.NTLM,
                                  auto_bind=True)
    print_done()

    # set up OU search
    query_parameters = {'search_base': ldap_basedn_groups,
                        'search_filter': f'(&({LDAPFILTER_GROUP})(displayName=*{ad_dl_query}*))',
                        'paged_size': LDAP_PAGE_SIZE,
                        'attributes': LDAP_GROUP_ATTRIBUTES}

    print(f'Querying AD groups...', end='')
    connection.search(**query_parameters)
    print_done()

    ad_dl_matchlist = [{'dn': entry.entry_dn, **entry.entry_attributes_as_dict}
                       for entry in connection.entries]

    if not ad_dl_matchlist:
        bad_choice()

    elif len(ad_dl_matchlist) > 1:
        # multiple matches found, present user with choice
        for count, ad_dl in enumerate(ad_dl_matchlist, 1):
            print(f'{count}: {ad_dl["displayName"][0]} ({ad_dl["dn"]})')

        try:
            dl_number = int(input('\nPlease enter number of DL to compare: '))
        except ValueError:
            bad_choice()

        if dl_number >= 0 and dl_number < len(ad_dl_matchlist)+1:
            dl_number -= 1
        else:
            bad_choice()

    else:
        # one match found, use it
        dl_number = 0

    # DL selected
    if dl_number >= 0:
        ad_dl_match = {'dn': ad_dl_matchlist[dl_number]['dn'],
                       'displayName': ad_dl_matchlist[dl_number]['displayName'][0]}
    else:
        bad_choice()

    if confirmed(f'AD group \"{ad_dl_match["displayName"]}\" selected, are you sure?'):
        ad_dl_userlist = list()
        query_parameters = {'search_base': ad_dl_match['dn'],
                            'search_filter': f'({LDAPFILTER_GROUP})',
                            'paged_size': LDAP_PAGE_SIZE,
                            'attributes': ['member']}
        print(f'Querying AD group membership...', end='')
        connection.search(**query_parameters)
        print_done()

        for member in connection.entries[0].member.values:
            print_status(f'Gathering details on {member[:(len(member)-ldap_basedn_len-1)]}')
            query_parameters = {'search_base': member,
                                'search_filter': LDAPFILTER_USER,
                                'paged_size': LDAP_PAGE_SIZE,
                                'attributes': LDAP_USER_ATTRIBUTES}
            connection.search(**query_parameters)
            if connection.entries:
                attributes = connection.entries[0]
                created = attributes.whenCreated.values[0]
                ad_dl_userlist.append({'name': attributes.displayName.values[0],
                                       'email': attributes.mail.values[0].lower(),
                                       'created': f'{created.year}-{created.month}-{created.day}'})

        print_status(' done.')

    else:
        bad_choice()

    # Buid list of AD user to add to team
    wx_team_additions = list()
    for ad_user in ad_dl_userlist:
        if not any(wx_user.personEmail.lower() == ad_user["email"] for wx_user in wx_team_members):
            if confirmed(f'AD user \"{ad_user["name"]}\" ({ad_user["created"]}) ' +
                         f'not in \"{wx_team_match["name"]}\" team, add?'):
                wx_team_additions.append(ad_user["email"])

    # Add users selected to team
    if wx_team_additions:
        for addition in wx_team_additions:
            api.team_memberships.create(wx_team_match['id'], personEmail=addition)
    else:
        print('### No users selected to add to team!')

    print('\n')

    # Notify if space includes users not in AD
    for wx_user in wx_team_members:
        if not any(ad_user['email'] == wx_user.personEmail.lower() for ad_user in ad_dl_userlist):
            print(f'\"{wx_user["name"]}\" not in {ad_dl_match["displayName"]} AD group!')

    print('\nComplete.')
    bot_name,
    logging_config,
    webhook_listener_base_url,
    webhook_port,
)

logging.basicConfig(**logging_config)
logger = logging.getLogger()

# initialize the database
db = TinyDB("db.json", indent=2, sort_keys=True)
db.table(name="_default", cache_size=0)
User = Query()

# Initialize the Bot in Webex Teams
api = WebexTeamsAPI(access_token=webex_teams_token)
bot_room_list = api.rooms.list()
registered_webhooks = api.webhooks.list()
webhook_listener = webhook_listener_base_url + f":{webhook_port}/{bot_name}"

# initialize the db for users who do not yet exist
for room in bot_room_list:
    print(f"bot is spawning in {room.title}")

app = Flask(__name__)

help_message_group = f"## Webex Teams Update Notifier\nThank you for adding me to your space.  I am here to alert you when new versions of Webex Teams are released by Cisco.  I will do this automatically unless you ask me not to.\n\n* If you want to stop receiving automatic updates simply @mention me and type `unsubscribe`.\n\n* If you want to opt back in simply @mention me and type `subscribe`\n\n* If you want to know the latest version, simply type `version`"
help_message_direct = f"## Webex Teams Update Notifier\nThank you for adding me to your space.  I am here to alert you when new versions of Webex Teams are released by Cisco.  I will do this automatically unless you ask me not to.\n\n* If you want to stop receiving automatic updates simply type `unsubscribe`.\n\n* If you want to opt back in simply type `subscribe`\n\n* If you want to know the latest version, simply type `version`"
release_notes = f"https://help.webex.com/en-us/mqkve8/Cisco-Webex-Teams-Release-Notes"
whats_new = f"https://help.webex.com/en-us/8dmbcr/What-s-New-in-Cisco-Webex-Teams"
Example #17
0
class WebExActions():
    access_token = 'YOUR BOT TOKEN'
    ccans_api = WebexTeamsAPI(access_token=access_token)

    def __init__(self):
        pass

    def tagged_Message_Actions(self, inMsg, dbObj, filterObj, adpCardObj,
                               webexObj):
        print("-->> WebExCalling.tagged_Message_Actions():")
        """Finds the data-object-id and if it exist, it will check if the user
            exist in people table or not, and if not, it will write details in DB

        Args:
        inmsg(dict): incoming tagged
        dbObject: object to send commands to databaseFuntions.py
        """
        userObjId = filterObj.get_object_id(inMsg)
        # filter markdown text to find type of issue
        issueType = filterObj.get_issue_type(inMsg)
        # save row in taggedMessage table
        dbObj.insert_in_tagged_table(issueType, inMsg)

        if dbObj.user_exist(userObjId) is False:
            userDet = self.ccans_api.people.get(userObjId)
            print("DB:Calling insert in people():")
            # save row in People table
            dbObj.insert_in_people(userObjId, userDet)
            print('user entry saved in table')
            print("Calling send_adaptive_card(new user)")
            adpCardObj.send_card(userObjId, issueType, dbObj, webexObj)
        else:
            print("Calling send_adaptive_card(existing user)")
            adpCardObj.send_card(userObjId, issueType, dbObj, webexObj)

    def non_tagged_message_action(self, inMsg, dbObj, filterObj, adpCardObj,
                                  webexObj):
        print("-->> WebExCalling.non_tagged_message_action():")
        if not inMsg['data'].get('markdown'):
            return False
        else:
            issueType = filterObj.get_issue_type(inMsg)
            messageText = inMsg['data']['markdown']
            print(messageText)
            possibleNickname = messageText.split('>')[-1].strip()
            searchName = dbObj.user_search_name(possibleNickname)
            dbObj.insert_in_nonTagged_table(issueType=issueType, inMsg=inMsg)
            print(searchName)
            if searchName == "NotFound":
                # send info to QM that alert failed
                roomId = inMsg['data']['roomId']
                failedMsg = inMsg['data']['markdown']
                failureMsg = f"""The message '{failedMsg}' appears to be in incorrect format and the CE has 'NOT' been notified of the case. Please fix the format. Tag bot and send message 'help' for more information. Think the format is correct ? Send the message screenshot to [email protected]"""
                webexObj.ccans_api.messages.create(roomId=roomId,
                                                   markdown=failureMsg)
            else:
                userId = searchName
                adpCardObj.send_card(userId,
                                     issueType=issueType,
                                     dbObj=dbObj,
                                     webexObj=webexObj)
                roomId = inMsg['data']['roomId']
                failedMsg = inMsg['data']['markdown']
                failureMsg = f"""The message '{failedMsg}' appears to be in incorrect format. CE is notified about the case however, please stick to the format and tag the CE. Tag bot and send message 'help' for more information. Think the format is correct ? Send the message screenshot to [email protected]"""
                webexObj.ccans_api.messages.create(roomId=roomId,
                                                   text=failureMsg)
Example #18
0
import utils.stock_utils as stocks
from webexteamssdk import WebexTeamsAPI, Webhook
import json

BOTNAME = "Stocks "
PRICE_CARD = "data/pricecard.json"

WEBEX_TEAMS_ACCESS_TOKEN = str(open("atoke").read())

WEBHOOK_NAME = "Stocks Bot"
MESSAGE_WEBHOOK_RESOURCE = "messages"
MESSAGE_WEBHOOK_EVENT = "created"
CARDS_WEBHOOK_RESOURCE = "attachmentActions"
CARDS_WEBHOOK_EVENT = "created"

api = WebexTeamsAPI(WEBEX_TEAMS_ACCESS_TOKEN)
bot = api.people.me()


def get_element(title, url, source, datetime, image, summary):
    return {
        'speak':
        'Stock News',
        'type':
        'ColumnSet',
        'columns': [{
            'type':
            'Column',
            'width':
            2,
            'items': [{
Example #19
0
from flask import Flask, request, jsonify
from webexteamssdk import WebexTeamsAPI
import os

# get environment variables
WT_BOT_TOKEN = os.environ['WT_BOT_TOKEN']

# uncomment next line if you are implementing a notifier bot
#WT_ROOM_ID = os.environ['WT_ROOM_ID']

# uncomment next line if you are implementing a controller bot
#WT_BOT_EMAIL = os.environ['WT_BOT_EMAIL']

# start Flask and WT connection
app = Flask(__name__)
api = WebexTeamsAPI(access_token=WT_BOT_TOKEN)


# defining the decorater and route registration for incoming alerts
@app.route('/', methods=['POST'])
def alert_received():
    raw_json = request.get_json()
    print(raw_json)

    # customize the behaviour of the bot here
    message = "Hi, I am a Webex Teams bot. Have a great day ☀! "

    # uncomment if you are implementing a notifier bot
    '''
    api.messages.create(roomId=WT_ROOM_ID, markdown=message)
    '''
Example #20
0
        else:
            print(parser.extract(message.text))
            parser.manage_text(message.text)
            print(parser.get_best_date())

if __name__ == '__main__':

    ci = CalendarIntegration()
    ci.authorize_api()

    parser = ParserICHack()

    # Read the configuration that contains the bot access token
    config = read_yaml_data('/opt/config/config.yaml')['hello_bot']
    teams_api = WebexTeamsAPI(access_token=config['teams_access_token'])

    # Get some required NGrok information
    ngrok_url = get_ngrok_url()

    # Define the name of webhook
    webhook_name = 'hello-bot-wb-hook'

    # Find any existing webhooks with this name and if this already exists then delete it
    dev_webhook = find_webhook_by_name(teams_api, webhook_name)
    if dev_webhook:
        delete_webhook(teams_api, dev_webhook)

    # Create a new teams webhook with the name defined above 
    create_webhook(teams_api, webhook_name, ngrok_url + '/teamswebhook')
Example #21
0
    def process_incoming_message(self):
        """
        Process an incoming message, determine the command and action,
        and determine reply.
        :return:
        """
        reply = None

        # Get the webhook data
        post_data = request.json

        # Determine the Teams Room to send reply to
        room_id = post_data["data"]["roomId"]

        if post_data["resource"] != "messages":
            cmdcheck = post_data["resource"].lower()
            if cmdcheck in self.commands.keys():
                api = WebexTeamsAPI(access_token=self.teams_bot_token)
                p = post_data
                reply = self.commands[cmdcheck]["callback"](api, p)
            else:
                return ""
        elif post_data["resource"] == "messages":
            # Get the details about the message that was sent.
            message_id = post_data["data"]["id"]
            message = self.teams.messages.get(message_id)
            if self.DEBUG:
                sys.stderr.write("Message content:" + "\n")
                sys.stderr.write(str(message) + "\n")

            # First make sure not processing a message from the bots
            # Needed to avoid the bot talking to itself
            # We check using IDs instead of emails since the email
            # of the bot could change while the bot is running
            # for example from [email protected] to [email protected]
            if message.personId in self.teams.people.me().id:
                if self.DEBUG:
                    sys.stderr.write("Ignoring message from our self" + "\n")
                return ""

            # Log details on message
            sys.stderr.write("Message from: " + message.personEmail + "\n")

            # Check if user is approved
            if len(self.approved_users
                   ) > 0 and message.personEmail not in self.approved_users:
                # User NOT approved
                sys.stderr.write(
                    "User: "******" is not approved to interact with bot. Ignoring.\n")
                return "Unapproved user"

            # Find the command that was sent, if any
            command = ""
            for c in sorted(self.commands.items()):
                if message.text.lower().find(c[0]) != -1:
                    command = c[0]
                    sys.stderr.write("Found command: " + command + "\n")
                    # If a command was found, stop looking for others
                    break

            # Build the reply to the user
            reply = ""

            # Take action based on command
            # If no command found, send the default_action
            if command in [""] and self.default_action:
                # noinspection PyCallingNonCallable
                reply = self.commands[self.default_action]["callback"](message)
            elif command in self.commands.keys():
                # noinspection PyCallingNonCallable
                reply = self.commands[command]["callback"](message)
            else:
                pass

        # allow command handlers to craft their own Teams message
        if reply and isinstance(reply, Response):
            # If the Response lacks a roomId, set it to the incoming room
            if not reply.roomId:
                reply.roomId = room_id
            reply = reply.as_dict()
            self.teams.messages.create(**reply)
            reply = "ok"
        # Support returning a list of Responses
        elif reply and isinstance(reply, list):
            for response in reply:
                # Make sure is a Response
                if isinstance(response, Response):
                    if not response.roomId:
                        response.roomId = room_id
                    self.teams.messages.create(**response.as_dict())

            reply = "ok"
        elif reply:
            self.teams.messages.create(roomId=room_id, markdown=reply)
        return reply
Example #22
0
writing, software distributed under the License is distributed on an "AS
IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
or implied.

"""

__author__ = "Russell Johnston"
__email__ = "*****@*****.**"
__version__ = "0.1.0"
__copyright__ = "Copyright (c) 2020 Cisco and/or its affiliates."
__license__ = "Cisco Sample Code License, Version 1.1"


import os
import random
from webexteamssdk import WebexTeamsAPI

# Instantiate a object for WebexTeamsAPI
BASE_URL = 'https://webexapis.com/v1/'
api = WebexTeamsAPI(base_url=BASE_URL)

ROOM_ID = '{{Enter Room ID}}'
MESSAGE_TEXT = f'Random number sent using SDK: {random.randint(1,999)}'

try:
    message = api.messages.create(ROOM_ID, text=MESSAGE_TEXT)
    print(f'New message created, with ID:\n{message.id}')
    print(message.text)
except ApiError as e:
    print(e)
Example #23
0
compliant_switches = 0
compliant_aps = 0
compliant_sec_appliances = 0
compliant_cameras = 0
non_compliant_devices = []

for device in myresponse:
    if device['firmware'] == switch_firmware:
        compliant_switches += 1
    elif device['firmware'] == ap_firmware:
        compliant_aps += 1
    elif device['firmware'] == sec_appliance_firmware:
        compliant_sec_appliances += 1
    elif device['firmware'] == camera_firmware:
        compliant_cameras += 1
    else:
        non_compliant_devices.append(device)

print(f'Total switches that meet the standard: {compliant_switches}')
print(f'Total APs that meet the standard: {compliant_aps}')
print(f'Total Security Appliances that meet the standard: {compliant_sec_appliances}')
print(f'Total Cameras that meet the standard: {compliant_cameras}')
print('Devices that will need to be manually checked:')

for device in non_compliant_devices:
    print(f"Serial#: {device['serial']}, Model#: {device['model']}")

#Post message to Teams
teams_api = WebexTeamsAPI(access_token=myWebexToken)
teams_api.messages.create(roomId=WebexRoomID, text='Report Completed')
Example #24
0
def add_poll(poll_name, poll_description, room_id, author):
    print(author)
    poll = Poll(poll_name, poll_description, room_id, author)
    all_polls[room_id] = poll


def add_translateObj(source_type, source_content, target_lang, roomId, author):
    print(author)
    translateObj = TranslateObj(source_type, source_content, target_lang,
                                roomId, author)
    translateObjs[roomId] = translateObj


def send_direct_message(person_email, message):
    teams_api.messages.create(toPersonEmail=person_email, text=message)


def send_message_in_room(room_id, message):
    teams_api.messages.create(roomId=room_id, text=message)


if __name__ == '__main__':
    teams_api = WebexTeamsAPI(access_token=WEBEX_TEAMS_ACCESS_TOKEN)
    create_webhook(teams_api, 'messages_webhook', '/messages_webhook',
                   'messages')
    create_webhook(teams_api, 'attachmentActions_webhook',
                   '/attachmentActions_webhook', 'attachmentActions')
    app.run(host='0.0.0.0', port=5000)

# mindmeld token: NThjOWViYjMtZTljZC00ZWQ4LWE3YWMtZDI5MjEwMjdlZTZlZTgyZjkxNWYtNjgy_PF84_4fd62afc-068e-4c49-b7bf-3ef92e2f33f5
# "id": "Y2lzY29zcGFyazovL3VzL1dFQkhPT0svZTY4NjIwYTUtMTRhZS00NWVmLWJlY2EtMWNmZjdiZTlhZDgw"
Example #25
0
from flask import Flask, request, jsonify
from webexteamssdk import WebexTeamsAPI

import os
import datetime

app = Flask(__name__)
api = WebexTeamsAPI(access_token=os.environ['WEBEX_TEAMS_ACCESS_TOKEN'])

ROOM_ID = os.environ['ROOM_ID']
DNAC_URL = "https://sandboxdnac2.cisco.com/"


@app.route('/dnac/event', methods=['POST'])
def dnac_event():
    """ Receive dnac webhook event and convert it into a Webex message"""
    dnac_notification = request.json

    title_emojii = "ЁЯУв"

    if dnac_notification['category'] == "ALERT":
        title_emojii = "ЁЯЪи"
    elif dnac_notification['category'] == "WARNING":
        title_emojii = "тЪая╕П"

    # construct the team message
    teams_message = "## {} {}\n".format(
        title_emojii, dnac_notification['details']['Assurance Issue Name'])
    teams_message += "* Severity: {}\n".format(dnac_notification['severity'])
    teams_message += "* Category: {}\n".format(dnac_notification['category'])
    teams_message += "* Timestamp: {}\n".format(
import json
import os
from flask import Flask, request
from webexteamssdk import WebexTeamsAPI

if not "WEBEX_TEAMS_ACCESS_TOKEN" in os.environ:
    webexAPI = WebexTeamsAPI(access_token='CHANGEME')
else:
    webexAPI = WebexTeamsAPI()

if not "WEBEX_TEAMS_ROOM_ID" in os.environ:
    os.environ["WEBEX_TEAMS_ROOM_ID"] = "CHANGEME"
    webexRoomId = os.environ["WEBEX_TEAMS_ROOM_ID"]
else:
    webexRoomId = os.environ["WEBEX_TEAMS_ROOM_ID"]

app = Flask(__name__)

@app.route('/', methods=['GET'])
def mainPage():
    print(os.environ)
    return("cisco-dnac-platform-webex-notifications -> by Robert Csapo ([email protected])")

@app.route('/sample', methods=['GET'])
def sample():
    jsonFile = "outputdata.json"
    with open(jsonFile) as f:
        data = json.load(f)
    issueTitle = data["title"]
    issuePriority = data["priority"]
    for item in data["enrichmentInfo"]["issueDetails"]["issue"]:
Example #27
0
from setup import token
from webexteamssdk import WebexTeamsAPI
import random
api = WebexTeamsAPI(access_token=token)
global room
room = None
while True:
    ct = input(">>> ")
    if ct.startswith("/"):
        ct.replace("/", "")
    if "exit" in ct or "stop" in ct:
        break
    elif ct.startswith("help"):
        print(
            "Command list:\n"
            "make - Makes a room and adds its room.ID to the clipboard\n"
            "join - Joins an email of your choice to the room.ID on clipboard\n"
            "say - Sends a message in the room.ID on clipboard\n"
            "choose - Shows a list of rooms the bot is currently in (DMs are displayed as \"Empty Title\")\n"
            "delete - If given operator permissions, the bot can delete the room on clipboard\n"
            "exit - Exits and terminates the script")
    elif ct.startswith("make"):
        try:
            if ct == "make":
                rng = random.randint(10000, 99999)
                room = api.rooms.create(f'newroom{rng}')
                print(f"Successfully created room named \"newroom{rng}\"")
            elif ct.startswith("make "):
                ct = ct.replace("make ", "")
                room = api.rooms.create(f'{ct}')
                print(f"Successfully created room named \"{ct}\"")
def main():
    """allows user to 'close' one or more spaces in Webex Teams"""
    with open(CONFIG_FILE, 'r') as config_file:
        config_params = yaml.full_load(config_file)

    wxteams_config = config_params['wxteams']
    wxteams_token = wxteams_config['auth_token']

    wxteams_spacequery = input(
        'Please enter part of name of space to list members of: ')

    # Query Webex Teams API for its list of users, webexteamssdk abstracts most of the work
    # https://github.com/CiscoDevNet/webexteamssdk/
    print('Building space list, please wait...')
    api = WebexTeamsAPI(access_token=wxteams_token)

    # Populate list of query matches from full list, case insensitive
    wx_space_matchlist = list()
    wx_space_fulllist = list(
        api.rooms.list(type='group', sortBy='lastactivity'))

    for wx_space in wx_space_fulllist:
        if wxteams_spacequery.upper() in wx_space.title.upper():
            wx_space_matchlist.append(matchlist_entry(wx_space))

    # Finalize space list
    if not wx_space_matchlist:
        bad_choice()

    elif len(wx_space_matchlist) > 1:
        # multiple matches found, present user with choice
        counter = 1
        print()
        for wx_space in wx_space_matchlist:
            print(
                f'{counter}: {wx_space["title"]}, last activity: {wx_space["lastActivity"]}'
            )
            counter += 1

        try:
            space_number = int(
                input('\nPlease enter number of space to query: '))
        except ValueError:
            bad_choice()

        if space_number >= 0 and space_number < len(wx_space_matchlist) + 1:
            space_number -= 1
        else:
            bad_choice()

    else:
        # one match found, use it
        space_number = 0

    # space selected
    if space_number >= 0 and space_number < len(wx_space_matchlist):
        wx_space_matchlist = [{
            'title':
            wx_space_matchlist[space_number]['title'],
            'lastActivity':
            wx_space_matchlist[space_number]['lastActivity'],
            'id':
            wx_space_matchlist[space_number]['id'],
            'creatorId':
            wx_space_matchlist[space_number]['creatorId']
        }]

    else:
        bad_choice()

    for wx_space in wx_space_matchlist:
        print(f'# Working on {wx_space["title"]}')
        list_members(wx_space['id'], api)
        print('# Complete.')
Example #29
0
import os
from pprint import pprint
from webexteamssdk import WebexTeamsAPI

# Get the absolute path for the directory where this file is located "here"
here = os.path.abspath(os.path.dirname(__file__))

# Get the absolute path for the project / repository root
project_root = os.path.abspath(os.path.join(here, ".."))

# Extend the system path to include the project root and import the env files
sys.path.insert(0, project_root)
import env_user  # noqa

# WEBEX TEAMS LIBRARY
teamsapi = WebexTeamsAPI(access_token=env_user.WT_ACCESS_TOKEN)

# Camera network ID, get video link
NETWORK_ID = "NETWORK ID"

# Camera serial number
CAMERA_SERIAL = "CAMERA SERIAL"

# mqtt setting
MQTT_SERVER = "iot.eclipse.org"
MQTT_PORT = 1883
MQTT_TOPIC = "/merakimv/"+ CAMERA_SERIAL + "/0"


# motion trigger setting
MOTION_ALERT_PEOPLE_COUNT_THRESHOLD = 1
def importData(conn, teamsAccessToken, startDate, endDate):

    cursor = conn.cursor()

    resp = cursor.execute(
        'SELECT COUNT(*) FROM sqlite_master WHERE type="table" AND name="messages"'
    )

    if resp.fetchone()[0] == 0:

        resp = cursor.execute('''
            CREATE TABLE messages (
                roomTitle text, 
                created text, 
                id text UNIQUE,
                parentId text, 
                roomId text, 
                roomType text, 
                text text, 
                personId text, 
                personEmail text, 
                html text, 
                mentionedPeople text,
                mentionedGroups text,
                threadCreated text )
            ''')

        conn.commit

    api = WebexTeamsAPI(access_token=teamsAccessToken)

    print('\nRetrieving active spaces...')

    rooms = api.rooms.list(sortBy='lastactivity')

    localTimeZone = get_localzone()

    startTime = localTimeZone.localize(datetime.strptime(
        startDate, '%Y-%m-%d'))
    endTime = localTimeZone.localize(
        datetime.strptime(endDate, '%Y-%m-%d') + timedelta(days=1))

    roomCount = 0
    messageCount = 0

    print('Importing messages (spaces/message)...', end='')

    roomsListRetries = 0

    while roomsListRetries < 2:

        try:

            for room in rooms:

                if room.lastActivity < startTime:
                    break

                roomCount += 1

                messages = api.messages.list(
                    roomId=room.id,
                    before=endTime.strftime('%Y-%m-%dT%H:%M:%S.%f%z'))

                data = []

                for message in messages:

                    if message.created < startTime:
                        break

                    if message.created > endTime:
                        continue

                    messageCount += 1

                    print(
                        f'\rImporting messages (spaces/messages): {roomCount} / {messageCount}',
                        end='')

                    mentionedPeople = message.mentionedPeople if hasattr(
                        message, 'mentionedPeople') else None
                    mentionedGroups = message.mentionedGroups if hasattr(
                        message, 'mentionedGroups') else None
                    parentId = message.json_data['parentId'] if (
                        'parentId' in message.json_data.keys()) else None
                    messageCreated = message.created.strftime(
                        '%Y-%m-%dT%H:%M:%S.%f%z')
                    threadCreated = messageCreated if parentId is None else None

                    data.append(
                        (room.title, messageCreated, message.id, parentId,
                         message.roomId, message.roomType, message.text,
                         message.personId, message.personEmail, message.html,
                         json.dumps(mentionedPeople),
                         json.dumps(mentionedGroups), threadCreated))

                try:

                    cursor.executemany(
                        'REPLACE INTO messages VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)',
                        data)

                    cursor.execute(
                        'REPLACE INTO messages ' +
                        '(roomTitle,created,id,parentId,roomId,roomType,text,personId,personEmail,html,mentionedPeople,mentionedGroups,threadCreated) '
                        +
                        'SELECT m2.roomTitle,m2.created,m2.id,m2.parentId,m2.roomId,m2.roomType,m2.text,m2.personId,m2.personEmail,m2.html,m2.mentionedPeople,m2.mentionedGroups,m1.created '
                        + 'FROM messages m1 ' +
                        'INNER JOIN messages m2 ON m1.id = m2.parentId')

                    conn.commit()

                except Exception as err:

                    print(f'nERROR in SQL REPLACE INTO: { err }')

        except webexteamssdk.ApiError as err:

            roomsListRetries += 1
            print(f'nERROR in rooms.list: { err }')

        break

    print()