kintone アプリで管理しているサイト情報を、Site24x7 と StatusCake に連携させてみる

# ０．はじめに

kintone アプリでサイト情報を管理していて、
監視サービスである Site24x7 と StatusCake と連携させたいな、
と思い、やってみました。

図で書くとこんな感じですかね。

![スクリーンショット 2017-12-06 16.44.56.png](https://qiita-image-store.s3.amazonaws.com/0/161939/9a3c9c89-bb26-bed8-5c48-896668b1333f.png)

# １．前提条件
1. Kintone
サイト情報を管理するアプリを作成しておきます。
<br><br>
フィールドコードは、以下を用意。
<br>
    * $id : ※デフォルト
    * ステータス : 「プロセス管理」の設定
    * Category : グルーピング、タグの設定 (「文字列」や「ドロップダウン」)
    * Title : サイトのタイトル (「文字列」)
    * Url : サイトの URL (「文字列」)
    * Notification : 監視サービスの設定 (「複数選択」や「チェックボックス」)
    * Users : 通知先のユーザー (「ユーザー選択」)
<br><br>
1. Site24x7
Site24x7 は有料のサービスですが、トライアルで利用出来るのでサインアップして、API キーを取得しておきます。
<br><br>
    * [Webサイト監視サービス、はじめの30日間ですべての機能を評価でサインアップ Site24x7](https://www.site24x7.com/ja/website-monitor.html)
    * [Site24x7 での API キーの取得のやり方 \- Qiita](http://qiita.com/kusokamayarou/items/e2eec05d8ea2acf43594)
<br><br>
1. StatusCake
Site24x7 はフリープランもあります。ただ、API の有効回数制限がありますので、ご注意を。有料版も安いやつがあるので、そちらを利用してもいいかも。サインアップしたら、API キーを取得しておきます。
    * [Our Pricing – StatusCake – Website Monitoring](https://www.statuscake.com/pricing/)
    * [StatusCake での API キーの取得のやり方 \- Qiita](http://qiita.com/kusokamayarou/items/f4bd7daed45fb13d0662)

# ２．プログラム

1. とりあえず、Python で書いてみました。
「長えよッ!!」との声が聞こえてきそうですが…。すいません…。
解説を後述しておきます。

    ```python:SetSiteMonitorsFromCybozu.py
    #!/usr/bin/python3.4 -tt
    # -*- coding: utf-8 -*-
    
    # ---1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----
    
    # ==============================================================================
    #
    # SetSiteMonitorsFromCybozu.py
    #
    #   * ex) $ ./SetSiteMonitorsFromCybozu.py
    #
    # ==============================================================================
    
    import sys
    import re
    import os
    import logging
    import codecs
    import json
    import datetime
    import requests
    import hashlib
    import subprocess
    import smtplib
    
    from urllib.parse import urlparse
    
    from email.mime.text import MIMEText
    from email.header import Header
    
    mypath=os.path.dirname(os.path.abspath(__file__))
    myname=os.path.basename(__file__)
    mybase,myext=os.path.splitext(myname)
    
    sys.stdout = codecs.getwriter('utf_8')(sys.stdout)
    
    logging.basicConfig(level=logging.DEBUG,
        format="[%(asctime)s] %(levelname)-8s %(filename)-20.20s (%(lineno)06d) %(funcName)-12.12s | %(message)s",
        datefmt='%Y-%m-%d %H:%M:%S',
        filename=(__file__ + ".log"),
        filemode='w')
    
    sh = logging.StreamHandler()
    sh.setLevel(logging.DEBUG)
    formatter = logging.Formatter("[%(asctime)s] %(levelname)-8s (%(lineno)06d) | %(message)s")
    sh.setFormatter(formatter)
    logging.getLogger().addHandler(sh)
    
    logging.debug("<<<<<<<< %s Start >>>>>>>>", __file__)
    
    # ------------------------------------------------------------------------------
    # Constant
    # ------------------------------------------------------------------------------
    nowdt = datetime.datetime.today()
    tmp_today = datetime.datetime.today()
    tmp_today_string = tmp_today.strftime('%Y-%m-%d %H:%M:%S')
    tmp_today_day_string = tmp_today.strftime('%d')
    
    # Mail
    HostSMTP = '[メールサーバ:ポート番号]'
    MailFrom = '[送信元メールアドレス]'
    MailTo = '[送信先メールアドレス]'
    LoginAccount = '[認証アカウント]'
    LoginPassword = '[認証パスワード]'
    
    # cybozu.com
    Cybozu_Url_Base = 'https://[取得したサブドメイン].cybozu.com'
    Cybozu_Auth_Headers_UserAPI = {
        'X-Cybozu-Authorization':'[APIキー]',
        'If-Modified-Since' : 'Thu, 01 Jun 1970 00:00:00 GMT'}
    Cybozu_Auth_Headers_KintoneAPI = {
        'X-Cybozu-API-Token' : '[KintoneのAPIトークンキー]',
        'Content-Type' : 'application/json; charset=UTF-8',
        'If-Modified-Since' : 'Thu, 01 Jun 1970 00:00:00 GMT'}
    
    # Site24x7
    Site24x7_Url_Base = 'https://www.site24x7.com/api'
    Site24x7_Auth_Headers = {
        'Content-Type' : 'application/json; charset=UTF-8',
        'Accept' : 'application/json; version=2.0',
        'Authorization' : '[APIキー]',
        'If-Modified-Since' : 'Thu, 01 Jun 1970 00:00:00 GMT'}
    
    # StatusCake
    StatusCake_Url_Base = 'https://app.statuscake.com/API'
    StatusCake_Auth_Headers = {'API':'[APIキー]',
        'Username' : '[ユーザーID]',
        'Content-Type' : 'application/json; charset=UTF-8',
        'If-Modified-Since' : 'Thu, 01 Jun 1970 00:00:00 GMT'}
    StatusCake_StatusCodes = ["204","205","206","303","400","401","403","404","405","406","408","410","429","444","494","495","496","499","500","501","502","504","505","506","507","511","598","599"]
    
    # ------------------------------------------------------------------------------
    # Variables
    # ------------------------------------------------------------------------------
    dic_users = {}
    dic_usergroups = {}
    dic_monitorgroups = {}
    dic_monitors = {'Web' : {}, '???' : {}, 'SSL':{}, 'DNS':{}}
    
    dic_cybozu_mail_user_s = {}
    dic_site24x7_user_mail_s = {}
    dic_site24x7_mail_user_s = {}
    
    # ------------------------------------------------------------------------------
    # Function
    # ------------------------------------------------------------------------------
    def getCybozuUsers():
        """Get Cybozu Users"""
        logging.debug("==== cybozu.com - Get Users Json ====")
        cybozu_users = requests.get(Cybozu_Url_Base + "/v1/users.json",
            headers=Cybozu_Auth_Headers_UserAPI)
        cybozu_users_json = cybozu_users.json()['users']
        logging.debug("cybozu_users_json:[%s]", cybozu_users_json)
        #
        logging.debug("==== cybozu.com - Set Users Dictionary ====")
        for n, k in enumerate(list(cybozu_users_json)):
            logging.debug("(%04d/%04d) cybozu.com - User | " \
                "ID:[%s] [%d] Code:[%s] Name:[%s] Mail:[%s] Tel:[%s]",
                n + 1, len(cybozu_users_json),
                cybozu_users_json[n]['id'],
                cybozu_users_json[n]['valid'],
                cybozu_users_json[n]['code'],
                cybozu_users_json[n]['name'],
                cybozu_users_json[n]['email'],
                cybozu_users_json[n]['phone'])
            user_id = cybozu_users_json[n]['code']
            if len(user_id) == 0:
                continue
            if user_id in dic_users:
                logging.error("OverLap | user_id:[%s]", user_id)
                continue
            dic_users[user_id] = {}
            dic_users[user_id]['cybozu'] = {
                'id' : cybozu_users_json[n]['id'],
                'valid' : cybozu_users_json[n]['valid'],
                'name' : cybozu_users_json[n]['name'],
                'email' : cybozu_users_json[n]['email'],
                'phone' : cybozu_users_json[n]['phone'],
            }
            mail = "" if cybozu_users_json[n]['email'] is None else cybozu_users_json[n]['email']
            if len(mail) == 0:
                continue
            if mail in dic_cybozu_mail_user_s:
                logging.warn("OverLap | MAIL:[%s]", mail)
                continue
            dic_cybozu_mail_user_s[mail] = user_id
    
    def getCybozuMonitors():
        """Get Cybozu Monitors"""
        logging.debug("==== cybozu.com - Get Monitors Json ====")
        cybozu_monitors = requests.get(Cybozu_Url_Base + "/k/v1/records.json",
            headers=Cybozu_Auth_Headers_KintoneAPI,
            data=json.dumps({
                "app": [Kintone アプリの ID],
                "query": "$id > 0 order by $id asc limit 500",
                "fields": [
                    "$id",
                    "ステータス",
                    "Category",
                    "Title",
                    "Url",
                    "Notification",
                    "Users"],
                "totalCount": "true"
            })
        )
        cybozu_monitors_json = cybozu_monitors.json()['records']
        logging.debug("cybozu_monitors_json:[%s]", cybozu_monitors_json)
        #
        logging.debug("==== cybozu.com - Set UserGroups & Monitors Dictionary ====")
        for n, k in enumerate(list(cybozu_monitors_json)):
            cybozu_monitors_json_ipaddress = ""
            if 'IP-Address' in cybozu_monitors_json[n]:
                cybozu_monitors_json_ipaddress = cybozu_monitors_json[n]['IP-Address']['value']
            cybozu_monitors_json_users = []
            cybozu_monitors_json_mails = []
            cybozu_monitors_json_phones = []
            for user in cybozu_monitors_json[n]['Users']['value']:
                cybozu_monitors_json_users.append(user['code'])
                if dic_users[user['code']]['cybozu']['email']:
                    if not dic_users[user['code']]['cybozu']['email'] in cybozu_monitors_json_mails:
                        cybozu_monitors_json_mails.append(dic_users[user['code']]['cybozu']['email'])
                if dic_users[user['code']]['cybozu']['phone']:
                    if not dic_users[user['code']]['cybozu']['phone'] in cybozu_monitors_json_phones:
                        cybozu_monitors_json_phones.append(dic_users[user['code']]['cybozu']['phone'])
                dic_users[user['code']]['cybozu']['used'] = True
            logging.debug("(%04d/%04d) cybozu.com - Monitors | " \
                "ID:[%s] Category:[%s] Title:[%s] Stuta:[%s] Url:[%s] IP:[%s] Notification:[%s] Users:[%s]",
                n + 1, len(cybozu_monitors_json),
                cybozu_monitors_json[n]['$id']['value'],
                cybozu_monitors_json[n]['Category']['value'],
                cybozu_monitors_json[n]['Title']['value'],
                cybozu_monitors_json[n]['ステータス']['value'],
                cybozu_monitors_json[n]['Url']['value'],
                cybozu_monitors_json_ipaddress,
                cybozu_monitors_json[n]['Notification']['value'],
                cybozu_monitors_json_users)
            #
            usergroup_id = ""
            if len(cybozu_monitors_json_mails) > 0:
                usergroup_id = hashlib.md5(":".join(sorted(cybozu_monitors_json_mails)).encode('utf-8')).hexdigest()
            if len(usergroup_id) > 0:
                if usergroup_id in dic_usergroups:
                    pass
                else:
                    dic_usergroups[usergroup_id] = {}
                    dic_usergroups[usergroup_id]['mails'] = sorted(cybozu_monitors_json_mails)
                    dic_usergroups[usergroup_id]['phones'] = sorted(cybozu_monitors_json_phones)
                    dic_usergroups[usergroup_id]['cybozu'] = {
                        'users' : sorted(cybozu_monitors_json_users)
                    }
            #
            parsed = urlparse(cybozu_monitors_json[n]['Url']['value'])
            #
            web_id = cybozu_monitors_json[n]['Url']['value'].rstrip('/')
            key = 'Web' if parsed.scheme in {"http", "https"} else '???'
            if len(web_id) > 0:
                if web_id in dic_monitors[key]:
                    logging.warn("OverLap | URL:[%s]", web_id)
                    pass
                else:
                    dic_monitors[key][web_id] = {}
                    dic_monitors[key][web_id]['usergroup_ids'] = [usergroup_id]
                    dic_monitors[key][web_id]['cybozu'] = {
                        'id' : cybozu_monitors_json[n]['$id']['value'],
                        'Category' : cybozu_monitors_json[n]['Category']['value'],
                        'Title' : cybozu_monitors_json[n]['Title']['value'],
                        'Status' : cybozu_monitors_json[n]['ステータス']['value'],
                        'Url' : cybozu_monitors_json[n]['Url']['value'],
                        'IP-Address' : cybozu_monitors_json_ipaddress,
                        'Notification' : cybozu_monitors_json[n]['Notification']['value'],
                        'users' : cybozu_monitors_json_users
                    }
            #
            ssl_id = ""
            if parsed.hostname is not None:
                if not parsed.hostname.endswith(".cybozu.com"):
                    ssl_id = parsed.hostname
            key = 'SSL'
            if len(ssl_id) > 0:
                if ssl_id in dic_monitors[key]:
                    if not 'web_ids' in dic_monitors[key][ssl_id]:
                        dic_monitors[key][ssl_id]['web_ids'] = []
                    if not web_id in dic_monitors[key][ssl_id]['web_ids']:
                        dic_monitors[key][ssl_id]['web_ids'].append(web_id)
                    if not 'usergroup_ids' in dic_monitors[key][ssl_id]:
                        dic_monitors[key][ssl_id]['usergroup_ids'] = []
                    if not usergroup_id in dic_monitors[key][ssl_id]['usergroup_ids']:
                        dic_monitors[key][ssl_id]['usergroup_ids'].append(usergroup_id)
                else:
                    dic_monitors[key][ssl_id] = {}
                    dic_monitors[key][ssl_id]['web_ids'] = [web_id]
                    dic_monitors[key][ssl_id]['usergroup_ids'] = [usergroup_id]
            #
            dns_id = ""
            if ssl_id.endswith(".com"):
                dns_id = ".".join(ssl_id.split(".")[-2:])
            elif ssl_id.endswith(".info"):
                dns_id = ".".join(ssl_id.split(".")[-2:])
            elif ssl_id.endswith(".co.jp"):
                dns_id = ".".join(ssl_id.split(".")[-3:])
            elif ssl_id.endswith(".go.jp"):
                dns_id = ".".join(ssl_id.split(".")[-3:])
            else:
                dns_id = ".".join(ssl_id.split(".")[-2:])
            key = 'DNS'
            if len(dns_id) > 0:
                if dns_id in dic_monitors[key]:
                    if not 'web_ids' in dic_monitors[key][dns_id]:
                        dic_monitors[key][dns_id]['web_ids'] = []
                    if not web_id in dic_monitors[key][dns_id]['web_ids']:
                        dic_monitors[key][dns_id]['web_ids'].append(web_id)
                    if not 'usergroup_ids' in dic_monitors[key][dns_id]:
                        dic_monitors[key][dns_id]['usergroup_ids'] = []
                    if not usergroup_id in dic_monitors[key][dns_id]['usergroup_ids']:
                        dic_monitors[key][dns_id]['usergroup_ids'].append(usergroup_id)
                else:
                    dic_monitors[key][dns_id] = {}
                    dic_monitors[key][dns_id]['web_ids'] =  [web_id]
                    dic_monitors[key][dns_id]['usergroup_ids'] = [usergroup_id]
            #
            monitorgroup_id = cybozu_monitors_json[n]['Category']['value']
            if len(monitorgroup_id) > 0:
                if not monitorgroup_id in dic_monitorgroups:
                    dic_monitorgroups[monitorgroup_id] = {}
                if not 'cybozu' in dic_monitorgroups[monitorgroup_id]:
                    dic_monitorgroups[monitorgroup_id]['cybozu'] = {}
                    dic_monitorgroups[monitorgroup_id]['cybozu']['monitors'] = []
                if not web_id in dic_monitorgroups[monitorgroup_id]['cybozu']['monitors']:
                    dic_monitorgroups[monitorgroup_id]['cybozu']['monitors'].append(web_id)
    
    def getSite24x7Users():
        """Get Site24x7 Users"""
        logging.debug("==== Site24x7 - Get Users Json ====")
        site24x7_users = requests.get(Site24x7_Url_Base + "/users",
            headers=Site24x7_Auth_Headers)
        site24x7_users_json = site24x7_users.json()['data']
        logging.debug("site24x7_users_json:[%s]", site24x7_users_json)
        #
        logging.debug("==== Site24x7 - Set Users Dictionary ====")
        for n, k in enumerate(list(site24x7_users_json)):
            logging.debug("(%04d/%04d) Site24x7 - Users | " \
                "ID:[%s] Role:[%d] Name:[%s] Mail:[%s] Tel:[%s] Groups:[%s]",
                n + 1, len(site24x7_users_json),
                site24x7_users_json[n]['user_id'],
                site24x7_users_json[n]['user_role'],
                site24x7_users_json[n]['display_name'],
                site24x7_users_json[n]['email_address'],
                site24x7_users_json[n]['mobile_settings'].get('mobile_number'),
                site24x7_users_json[n]['user_groups'])
            cybozu_user_id = ""
            if site24x7_users_json[n]['email_address'] in dic_cybozu_mail_user_s:
                cybozu_user_id = dic_cybozu_mail_user_s[site24x7_users_json[n]['email_address']]
            if len(cybozu_user_id) > 0:
                if cybozu_user_id in dic_users:
                    dic_users[cybozu_user_id]['Site24x7'] = site24x7_users_json[n]
                else:
                    dic_users[cybozu_user_id] = {}
                    dic_users[cybozu_user_id]['Site24x7'] = site24x7_users_json[n]
            site24x7_user_id = site24x7_users_json[n]['user_id']
            if len(site24x7_user_id) > 0:
                if site24x7_user_id in dic_site24x7_user_mail_s:
                    logging.wran("OverLap | USERID:[%s]", site24x7_user_id)
                    pass
                else:
                    dic_site24x7_user_mail_s[site24x7_user_id] = site24x7_users_json[n]['email_address']
    
    def setSite24x7Users():
        """Set Site24x7 Users"""
        logging.debug("==== Site24x7 - Set Users to System ====")
        del_users = []
        for n, k in enumerate(list(dic_users)):
            logging.debug("(%04d/%04d) Users - [%s]:[%s]",
                n + 1, len(dic_users),
                k, dic_users[k])
            Site24x7_Url_Users = Site24x7_Url_Base + "/users"
            site24x7_users_res = ""
            if 'cybozu' in dic_users[k] and 'used' in dic_users[k]['cybozu'] and dic_users[k]['cybozu']['used']:
                mobile_number = re.sub('[-() ]', '',dic_users[k]['cybozu']['phone']).lstrip('0')
                if mobile_number:
                    if mobile_number[1:2] == "0":
                        pass
                    else:
                        mobile_number = ""
                else:
                    mobile_number = ""
                Site24x7_Payload_Users_Update = {
                    "user_role": "3",
                    "mobile_settings": {
                        "country_code": "81",
                        "mobile_number": mobile_number
                    },         
                    "alert_settings":{
                        "email_format":0,
                        "dont_alert_on_days":[],
                        "alerting_period":{
                            "start_time":"00:00",
                            "end_time":"24:00"
                        },     
                        "down":[1,2,3],
                        "trouble":[1,2,3],
                        "up":[1,2,3]
                    },         
                    "display_name":dic_users[k]['cybozu']['name'],
                    "email_address":dic_users[k]['cybozu']['email'],
                    "notify_medium":[1,2,3]
                }
                if 'Site24x7' in dic_users[k]:
                    if dic_users[k]['Site24x7']['user_role'] != 0:
                        Site24x7_Payload_Users_Update['user_role'] = dic_users[k]['Site24x7']['user_role']
                    update_flag = False
                    if dic_users[k]['Site24x7']['mobile_settings'].get('mobile_number') != Site24x7_Payload_Users_Update['mobile_settings'].get('mobile_number'):
                        update_flag = True
                    if dic_users[k]['Site24x7'].get('alert_settings') != Site24x7_Payload_Users_Update.get('alert_settings'):
                        update_flag = True
                    if dic_users[k]['Site24x7'].get('email_address') != Site24x7_Payload_Users_Update.get('email_address'):
                        update_flag = True
                    if dic_users[k]['Site24x7'].get('display_name') != Site24x7_Payload_Users_Update.get('display_name'):
                        update_flag = True
                    if update_flag:
                        logging.info("Site24x7 - User - Update")
                        logging.info("dic_users[k]:[%s]",dic_users[k]['Site24x7'])
                        logging.info("Site24x7_Payload_Users_Update:[%s]",Site24x7_Payload_Users_Update)
                        Site24x7_Url_Users += "/" + dic_users[k]['Site24x7']['user_id']
                        Site24x7_Payload_Users_Update['user_role'] = dic_users[k]['Site24x7']['user_role']
                        if len(dic_users[k]['Site24x7']['user_groups']) > 0:
                            Site24x7_Payload_Users_Update['user_groups'] = dic_users[k]['Site24x7']['user_groups']
                        logging.debug("Site24x7_Url_Users:[%s]", Site24x7_Url_Users)
                        logging.debug("Site24x7_Payload_Users_Update:[%s]", Site24x7_Payload_Users_Update)
                        site24x7_users_res = requests.put(Site24x7_Url_Users,
                            data=json.dumps(Site24x7_Payload_Users_Update), headers=Site24x7_Auth_Headers)
                        site24x7_users_res_json = site24x7_users_res.json()
                        logging.debug("site24x7_users_res_json:[%s]", site24x7_users_res_json)
                        if site24x7_users_res_json['message'] == 'success':
                            dic_users[k]['Site24x7'] = site24x7_users_res_json['data']
                        else:
                            logging.error("site24x7_users_res_json:[%s]", site24x7_users_res_json)
                else:
                    logging.info("Site24x7 - User - Insert")
                    logging.debug("Site24x7_Url_Users:[%s]", Site24x7_Url_Users)
                    logging.debug("Site24x7_Payload_Users_Update:[%s]", Site24x7_Payload_Users_Update)
                    site24x7_users_res = requests.post(Site24x7_Url_Users,
                        data=json.dumps(Site24x7_Payload_Users_Update), headers=Site24x7_Auth_Headers)
                    site24x7_users_res_json = site24x7_users_res.json()
                    logging.debug("site24x7_users_res_json:[%s]", site24x7_users_res_json)
                    if site24x7_users_res_json['message'] == 'success':
                        dic_users[k]['Site24x7'] = site24x7_users_res_json['data']
                        site24x7_user_id = site24x7_users_res_json['data']['user_id']
                        if len(site24x7_user_id) > 0:
                            if site24x7_user_id in dic_site24x7_user_mail_s:
                                logging.warn("OverLap | USERID:[%s]", site24x7_user_id)
                                pass
                            else:
                                dic_site24x7_user_mail_s[site24x7_user_id] = site24x7_users_res_json['data']['email_address']
                    else:
                        logging.error("site24x7_users_res_json:[%s]", site24x7_users_res_json)
            else:
                if 'Site24x7' in dic_users[k]: 
                    if 'user_role' in dic_users[k]['Site24x7']: 
                        if dic_users[k]['Site24x7']['user_role'] < 1 or dic_users[k]['Site24x7']['user_role'] > 2:
                            del_users.append(k)
        return del_users
    
    def unsetSite24x7Users(del_users):
        """UnSet Site24x7 Users"""
        logging.debug("==== Site24x7 - UnSet Users to System ====")
        for n, k in enumerate(del_users):
            logging.debug("(%04d/%04d) Users - [%s]:[%s]",
                n + 1, len(del_users),
                k, dic_users[k])
            Site24x7_Url_Users = Site24x7_Url_Base + "/users"
            logging.info("Site24x7 - User - Delete")
            Site24x7_Url_Users += "/" + dic_users[k]['Site24x7']['user_id']
            logging.info("Site24x7_Url_Users:[%s]", Site24x7_Url_Users)
            site24x7_users_res = requests.delete(Site24x7_Url_Users,
                headers=Site24x7_Auth_Headers)
            site24x7_users_res_json = site24x7_users_res.json()
            logging.info("site24x7_users_res_json:[%s]", site24x7_users_res_json)
            if site24x7_users_res_json['message'] == 'success':
                val = dic_users[k].pop('Site24x7')
                site24x7_user_id =  val['user_id']
                if len(site24x7_user_id) > 0:
                    if site24x7_user_id in dic_site24x7_user_mail_s:
                        dic_site24x7_user_mail_s.pop(site24x7_user_id)
                    else:
                        logging.warn("Not | USERID:[%s]", site24x7_user_id)
                        pass
            else:
                logging.error("site24x7_users_res_json:[%s]", site24x7_users_res_json)
    
    def getSite24x7UserGroups():
        """Get Site24x7 UserGroups"""
        logging.debug("==== Site24x7 - Get UserGroups Json ====")
        site24x7_usergroups = requests.get(Site24x7_Url_Base + "/user_groups",
            headers=Site24x7_Auth_Headers)
        site24x7_usergroups_json = site24x7_usergroups.json()['data']
        logging.debug("site24x7_usergroups_json:[%s]", site24x7_usergroups_json)
        for n, k in enumerate(list(site24x7_usergroups_json)):
            logging.debug("(%04d/%04d) Site24x7 - UserGroups | ID:[%s] Master:[%d] Name:[%s] Users:[%s]",
                n + 1, len(site24x7_usergroups_json),
                site24x7_usergroups_json[n]['user_group_id'],
                site24x7_usergroups_json[n]['is_master_group'],
                site24x7_usergroups_json[n]['display_name'],
                site24x7_usergroups_json[n]['users'])
            usergroup_id = site24x7_usergroups_json[n]['display_name']
            if len(usergroup_id) > 0:
                if not usergroup_id in dic_usergroups:
                    dic_usergroups[usergroup_id] = {}
                if not 'Site24x7' in dic_usergroups[usergroup_id]:
                    dic_usergroups[usergroup_id]['Site24x7'] = {}
                dic_usergroups[usergroup_id]['Site24x7'][site24x7_usergroups_json[n]['user_group_id']] = site24x7_usergroups_json[n]
    
    def setSite24x7UserGroups():
        """Set Site24x7 UserGroups"""
        logging.debug("==== Site24x7 - Set UserGroups to System ====")
        del_usergroups = {}
        for n, k in enumerate(list(dic_usergroups)):
            logging.debug("(%04d/%04d) UserGroups - [%s]:[%s]",
                n + 1, len(dic_usergroups),
                k, dic_usergroups[k])
            site24x7_usergroups_res = ""
            if 'cybozu' in dic_usergroups[k]:
                if 'Site24x7' in dic_usergroups[k]: 
                    nn = 0
                    for kk in list(dic_usergroups[k]['Site24x7']):
                        if nn == 0:
                            logging.debug("Site24x7 - UserGroups - Update")
                            pass
                        else:
                            logging.info("Site24x7 - UserGroups - Delete")
                            site24x7_usergroups_res = requests.delete(Site24x7_Url_Base + "/user_groups/" + kk,
                                headers=Site24x7_Auth_Headers)
                            site24x7_usergroups_res_json = site24x7_usergroups_res.json()
                            logging.debug("site24x7_usergroups_res_json:[%s]", site24x7_usergroups_res_json)
                            if site24x7_usergroups_res_json['message'] == 'success':
                                dic_usergroups[k]['Site24x7'].pop(kk)
                            else:
                                logging.error("site24x7_usergroups_res_json:[%s]", site24x7_usergroups_res_json)
                        nn += 1
                else:
                    logging.info("Site24x7 - UserGroups - Insert")
                    users = []
                    dic_usergroups[k]['Site24x7'] = {}
                    dic_site24x7_mail_user_s = {vvv:kkk for kkk, vvv in dic_site24x7_user_mail_s.items()}
                    for mail in dic_usergroups[k]['mails']:
                        user = dic_site24x7_mail_user_s[mail]
                        logging.debug("(%04d) UserGroups - [%s]:[%s]", n, mail, user)
                        users.append(user)
                    
                    Site24x7_Payload_UserGroups_Insert = {
                        "display_name": k,
                        "users": users,
                    }
                    logging.debug("Site24x7_Payload_UserGroups_Insert:[%s]", Site24x7_Payload_UserGroups_Insert)
                    site24x7_usergroups_res = requests.post(Site24x7_Url_Base + "/user_groups",
                        data=json.dumps(Site24x7_Payload_UserGroups_Insert), headers=Site24x7_Auth_Headers)
                    site24x7_usergroups_res_json = site24x7_usergroups_res.json()
                    logging.debug("site24x7_usergroups_res_json:[%s]", site24x7_usergroups_res_json)
                    if site24x7_usergroups_res_json['message'] == 'success':
                        dic_usergroups[k]['Site24x7'][site24x7_usergroups_res_json['data']['user_group_id']] = site24x7_usergroups_res_json['data']
                    else:
                        logging.error("site24x7_usergroups_res_json:[%s]", site24x7_usergroups_res_json)
            else:
                if 'Site24x7' in dic_usergroups[k]:
                    for kk in list(dic_usergroups[k]['Site24x7']):
                        if dic_usergroups[k]['Site24x7'][kk]['display_name'] in {"管理グループ", "ネットワークチーム", "アプリケーションチーム"}:
                            pass
                        else:
                            del_usergroups[kk] = k
        return del_usergroups
    
    def unsetSite24x7UserGroups(del_usergroups):
        """UnSet Site24x7 UserGroups"""
        logging.debug("==== Site24x7 - UnSet UserGroups to System ====")
        logging.debug("del_usergroups:[%s]", del_usergroups)
        for n, kk in enumerate(del_usergroups.keys()):
            logging.debug("(%04d/%04d) UserGroups - [%s]:[%s]",
                n + 1, len(del_usergroups),
                kk, del_usergroups[kk])
            k = del_usergroups[kk]
            logging.info("Site24x7 - UserGroups - Delete")
            site24x7_usergroups_res = requests.delete(Site24x7_Url_Base + "/user_groups/" + kk,
                headers=Site24x7_Auth_Headers)
            site24x7_usergroups_res_json = site24x7_usergroups_res.json()
            logging.info("site24x7_usergroups_res_json:[%s]", site24x7_usergroups_res_json)
            if site24x7_usergroups_res_json['message'] == 'success':
                dic_usergroups[k]['Site24x7'].pop(kk)
            else:
                logging.error("site24x7_usergroups_res_json:[%s]", site24x7_usergroups_res_json)
    
    def getSite24x7MonitorGroups():
        """Get Site24x7 MonitorGroups"""
        logging.debug("==== Site24x7 - Get MonitorGroups Json ====")
        site24x7_monitorgroups = requests.get(Site24x7_Url_Base + "/monitor_groups",
            headers=Site24x7_Auth_Headers)
        site24x7_monitorgroups_json = site24x7_monitorgroups.json()['data']
        logging.debug("site24x7_monitorgroups_json:[%s]", site24x7_monitorgroups_json)
        for n, k in enumerate(list(site24x7_monitorgroups_json)):
            logging.debug("(%04d/%04d) Site24x7 - MonitorsGroups | ID:[%s] Name:[%s] Count:[%04d] Monitors:[%s]",
                n + 1, len(site24x7_monitorgroups_json),
                site24x7_monitorgroups_json[n]['group_id'],
                site24x7_monitorgroups_json[n]['display_name'],
                site24x7_monitorgroups_json[n]['health_threshold_count'],
                site24x7_monitorgroups_json[n]['monitors'] if 'monitors' in site24x7_monitorgroups_json[n] else [])
            monitorgroup_id = site24x7_monitorgroups_json[n]['group_id']
            monitorgroup_name = site24x7_monitorgroups_json[n]['display_name']
            if not monitorgroup_name in dic_monitorgroups:
                dic_monitorgroups[monitorgroup_name] = {}
            if not 'Site24x7' in dic_monitorgroups[monitorgroup_name]:
                dic_monitorgroups[monitorgroup_name]['Site24x7'] = {}
            if not monitorgroup_id in dic_monitorgroups[monitorgroup_name]['Site24x7']:
                dic_monitorgroups[monitorgroup_name]['Site24x7'][monitorgroup_id] = site24x7_monitorgroups_json[n]
    
    def setSite24x7MonitorGroups():
        """Set Site24x7 MonitorGroups"""
        logging.debug("==== Site24x7 - Set MonitorGroups to System ====")
        del_monitorgroups = {}
        for n, k in enumerate(list(dic_monitorgroups)):
            logging.debug("(%04d/%04d) Site24x7 - MonitorGroups - [%s]:[%s]",
                n + 1, len(dic_monitorgroups),
                k, dic_monitorgroups[k])
            site24x7_monitorgroups_res = ""
            if 'cybozu' in dic_monitorgroups[k]:
                if 'Site24x7' in dic_monitorgroups[k]: 
                    nn = 0
                    for kk in list(dic_monitorgroups[k]['Site24x7']):
                        if nn == 0:
                            logging.debug("Site24x7 - MonitorGroups - Update")
                            pass
                        else:
                            del_monitorgroups[kk] = k
                        nn += 1
                else:
                    logging.info("Site24x7 - MonitorGroups - Insert")
                    Site24x7_Payload_MonitorGroups_Insert = {
                        "display_name": k,
                        "description": k,
                        "monitors": [],
                    }
                    logging.debug("Site24x7_Payload_MonitorGroups_Insert:[%s]", Site24x7_Payload_MonitorGroups_Insert)
                    site24x7_monitorgroups_res = requests.post(Site24x7_Url_Base + "/monitor_groups",
                        data=json.dumps(Site24x7_Payload_MonitorGroups_Insert), headers=Site24x7_Auth_Headers)
                    site24x7_monitorgroups_res_json = site24x7_monitorgroups_res.json()
                    logging.debug("site24x7_monitorgroups_res_json:[%s]", site24x7_monitorgroups_res_json)
                    if site24x7_monitorgroups_res_json['message'] == 'success':
                        dic_monitorgroups[k]['Site24x7'][site24x7_usergroups_res_json['data']['group_id']] = site24x7_usergroups_res_json['data']
                    else:
                        logging.error("site24x7_monitorgroups_res_json:[%s]", site24x7_monitorgroups_res_json)
            else:
                if 'Site24x7' in dic_monitorgroups[k]:
                    for kk in list(dic_monitorgroups[k]['Site24x7']):
                        del_monitorgroups[kk] = k
                else:
                    pass
        return del_monitorgroups
    
    def unsetSite24x7MonitorGroups(del_monitorgroups):
        """UnSet Site24x7 MonitorGroups"""
        logging.debug("==== Site24x7 - UnSet MonitorGroups to System ====")
        for n, kk in enumerate(del_monitorgroups.keys()):
            logging.debug("(%04d/%04d) Site24x7 - MonitorGroups - [%s]:[%s]",
                n + 1, len(dic_monitorgroups),
                kk, del_monitorgroups[kk])
            k = del_monitorgroups[kk]
            logging.info("Site24x7 - MonitorGroups - Delete")
            site24x7_monitorgroups_res = requests.delete(Site24x7_Url_Base + "/monitor_groups/" + kk,
                headers=Site24x7_Auth_Headers)
            site24x7_monitorgroups_res_json = site24x7_monitorgroups_res.json()
            logging.info("site24x7_monitorgroups_res_json:[%s]", site24x7_monitorgroups_res_json)
            if site24x7_monitorgroups_res_json['message'] == 'success':
                dic_monitorgroups[k]['Site24x7'].pop(kk)
            else:
                logging.error("site24x7_monitorgroups_res_json:[%s]", site24x7_monitorgroups_res_json)
    
    def getSite24x7Monitors():
        """Get Site24x7 Monitors"""
        logging.debug("==== Site24x7 - Get Monitors Json ====")
        site24x7_monitors = requests.get(Site24x7_Url_Base + "/monitors",
            headers=Site24x7_Auth_Headers)
        site24x7_monitors_json = site24x7_monitors.json()['data']
        logging.debug("site24x7_monitors_json:[%s]", site24x7_monitors_json)
        for n, k in enumerate(list(site24x7_monitors_json)):
            logging.debug("(%04d) Site24x7 - Monitors:[%s]", n, json.dumps(site24x7_monitors_json[n]))
            key = "???"
            tgt = ""
            if site24x7_monitors_json[n]['type'] in {"URL"}:
                key = "Web"
                tgt = site24x7_monitors_json[n]['website'].rstrip('/')
            elif site24x7_monitors_json[n]['type'] in {"HOMEPAGE"}:
                key = "???"
                tgt = site24x7_monitors_json[n]['website'].rstrip('/')
            elif site24x7_monitors_json[n]['type'] in {"DNS"}:
                key = "DNS"
                tgt = site24x7_monitors_json[n]['domain_name'].rstrip('/')
            elif site24x7_monitors_json[n]['type'] in {"PORT-SMTP"}:
                key = "???"
                tgt = site24x7_monitors_json[n]['host_name'].rstrip('/')
            elif site24x7_monitors_json[n]['type'] in {"SSL_CERT"}:
                key = "SSL"
                tgt = site24x7_monitors_json[n]['domain_name'].rstrip('/')
            else:
                pass
            logging.debug("(%04d/%04d) Site24x7 - Monitors | " \
                "ID:[%s] State:[%d] Type:[%s] Name:[%s] Tgt:[%s] AlertGroups:[%s]",
                n + 1, len(site24x7_monitors_json),
                site24x7_monitors_json[n]['monitor_id'],
                site24x7_monitors_json[n]['state'],
                site24x7_monitors_json[n]['type'],
                site24x7_monitors_json[n]['display_name'],
                tgt,
                site24x7_monitors_json[n]['user_group_ids'])
            if len(tgt) > 0:
                if tgt in dic_monitors[key]:
                    dic_monitors[key][tgt]['Site24x7'] = site24x7_monitors_json[n]
                else:
                    dic_monitors[key][tgt] = {}
                    dic_monitors[key][tgt]['Site24x7'] = site24x7_monitors_json[n]
    
    def setSite24x7Monitors():
        """Set Site24x7 Monitors"""
        logging.debug("==== Site24x7 - Set Monitors (Web) to System ====")
        del_monitors = []
        for n, k in enumerate(list(dic_monitors['Web'])):
            logging.debug("(%04d/%04d) Site24x7 - Monitors (Web) - [%s]:[%s]",
                n + 1, len(dic_monitors['Web']),
                k, dic_monitors['Web'][k])
            site24x7_monitors_res = ""
            site24x7_monitors_res_json = None
            if 'cybozu' in dic_monitors['Web'][k]:
                monitor_groups = list(dic_monitorgroups[dic_monitors['Web'][k]['cybozu']['Category']]['Site24x7'].keys())
                logging.debug("monitor_groups:[%s]", monitor_groups)
                user_group_ids = []
                for usergroup_id in dic_monitors['Web'][k]['usergroup_ids']:
                    if not usergroup_id in dic_usergroups:
                        continue
                    if not 'Site24x7' in dic_usergroups[usergroup_id]:
                        continue
                    logging.debug("dic_usergroups[usergroup_id]['Site24x7']:[%s]", dic_usergroups[usergroup_id]['Site24x7'])
                    for kk in dic_usergroups[usergroup_id]['Site24x7'].keys():
                        user_group_ids.append(dic_usergroups[usergroup_id]['Site24x7'][kk]['user_group_id'])
                if len(user_group_ids) == 0:
                    user_group_ids = ['215015000000025003']
                logging.debug("user_group_ids:[%s]", user_group_ids)
                Site24x7_Payload_Monitors_Update = {
                    "display_name": k,
                    "type": 'URL',
                    "website": k,
                    "check_frequency": '5',
                    "timeout": 15,
                    "location_profile_id": "215015000004406005",
                    "notification_profile_id": "215015000000025063",
                    "threshold_profile_id": "215015000000025114",
                    "user_group_ids": user_group_ids,
                    "http_method": "G",
                    "monitor_groups": monitor_groups,
                    "use_ipv6": False,
                    "match_case": True,
                    "probe_proxy_enabled": False,     
                    "auth_method": 'B',               
                    "ssl_protocol": 'Auto',           
                    "use_name_server": False,
                }
                if 'Site24x7' in dic_monitors['Web'][k] \
                    and 'type' in dic_monitors['Web'][k]['Site24x7'] \
                    and dic_monitors['Web'][k]['Site24x7']['type'] == 'URL': 
                    if dic_monitors['Web'][k]['Site24x7']['display_name'] != Site24x7_Payload_Monitors_Update["display_name"] \
                    or dic_monitors['Web'][k]['Site24x7']['website'] != Site24x7_Payload_Monitors_Update["website"] \
                    or dic_monitors['Web'][k]['Site24x7']['check_frequency'] != Site24x7_Payload_Monitors_Update["check_frequency"] \
                    or dic_monitors['Web'][k]['Site24x7']['timeout'] != Site24x7_Payload_Monitors_Update["timeout"] \
                    or dic_monitors['Web'][k]['Site24x7']['location_profile_id'] != Site24x7_Payload_Monitors_Update["location_profile_id"] \
                    or dic_monitors['Web'][k]['Site24x7']['notification_profile_id'] != Site24x7_Payload_Monitors_Update["notification_profile_id"] \
                    or dic_monitors['Web'][k]['Site24x7']['threshold_profile_id'] != Site24x7_Payload_Monitors_Update["threshold_profile_id"] \
                    or dic_monitors['Web'][k]['Site24x7']['user_group_ids'] != Site24x7_Payload_Monitors_Update["user_group_ids"] \
                    or dic_monitors['Web'][k]['Site24x7']['http_method'] != Site24x7_Payload_Monitors_Update["http_method"] \
                    or dic_monitors['Web'][k]['Site24x7']['monitor_groups'] != Site24x7_Payload_Monitors_Update["monitor_groups"] \
                    or dic_monitors['Web'][k]['Site24x7']['use_ipv6'] != Site24x7_Payload_Monitors_Update["use_ipv6"] \
                    or dic_monitors['Web'][k]['Site24x7']['match_case'] != Site24x7_Payload_Monitors_Update["match_case"] \
                    or dic_monitors['Web'][k]['Site24x7']['probe_proxy_enabled'] != Site24x7_Payload_Monitors_Update["probe_proxy_enabled"] \
                    or dic_monitors['Web'][k]['Site24x7']['auth_method'] != Site24x7_Payload_Monitors_Update["auth_method"] \
                    or dic_monitors['Web'][k]['Site24x7']['ssl_protocol'] != Site24x7_Payload_Monitors_Update["ssl_protocol"] \
                    or dic_monitors['Web'][k]['Site24x7']['use_name_server'] != Site24x7_Payload_Monitors_Update["use_name_server"]:
                        logging.info("Site24x7 - Monitors (Web) - Update")
                        logging.info("dic_monitors['Web'][k]['Site24x7']:[%s]", dic_monitors['Web'][k]['Site24x7'])
                        logging.info("Site24x7_Payload_Monitors_Update:[%s]", Site24x7_Payload_Monitors_Update)
                        site24x7_monitors_res = requests.put(Site24x7_Url_Base + "/monitors/" + dic_monitors['Web'][k]['Site24x7']['monitor_id'],
                            data=json.dumps(Site24x7_Payload_Monitors_Update), headers=Site24x7_Auth_Headers)
                        site24x7_monitors_res_json = site24x7_monitors_res.json()
                        logging.info("site24x7_monitors_res_json:[%s]", site24x7_monitors_res_json)
                        if site24x7_monitors_res_json['message'] == 'success':
                            site24x7_monitors_res_json['data']['state'] = dic_monitors['Web'][k]['Site24x7']['state']
                            dic_monitors['Web'][k]['Site24x7'] = site24x7_monitors_res_json['data']
                        else:
                            logging.error("site24x7_monitors_res_json:[%s]", site24x7_monitors_res_json)
                            logging.error("Site24x7_Payload_Monitors_Update:[%s]", Site24x7_Payload_Monitors_Update)
                else:
                    logging.info("Site24x7 - Monitors (Web) - Insert")
                    logging.info("Site24x7_Payload_Monitors_Update:[%s]", Site24x7_Payload_Monitors_Update)
                    site24x7_monitors_res = requests.post(Site24x7_Url_Base + "/monitors",
                        data=json.dumps(Site24x7_Payload_Monitors_Update), headers=Site24x7_Auth_Headers)
                    site24x7_monitors_res_json = site24x7_monitors_res.json()
                    if site24x7_monitors_res_json['message'] == 'success':
                        site24x7_monitors_res_json['data']['state'] = 5
                        dic_monitors['Web'][k]['Site24x7'] = site24x7_monitors_res_json['data']
                    else:
                        logging.error("site24x7_monitors_res_json:[%s]", site24x7_monitors_res_json)
                        logging.error("Site24x7_Payload_Monitors_Update:[%s]", Site24x7_Payload_Monitors_Update)
                site24x7_monitors_res = requests.get(Site24x7_Url_Base + "/current_status/" + dic_monitors['Web'][k]['Site24x7']['monitor_id'],
                    headers=Site24x7_Auth_Headers)
                site24x7_monitors_res_json = site24x7_monitors_res.json()
                logging.debug("site24x7_monitors_res_json:[%s]", site24x7_monitors_res_json)
                if site24x7_monitors_res_json['message'] == 'success':
                    if 'status' in site24x7_monitors_res_json['data']:
                        if dic_monitors['Web'][k]['Site24x7']['state'] == 5:
                            # ID    Status
                            # 0     Down
                            # 1     Up
                            # 2     Trouble
                            # 5     Suspended
                            # 7     Maintenance
                            # 9     Discovery
                            # 10    Configuration Error
                            if site24x7_monitors_res_json['data']['status'] == 9 \
                            or site24x7_monitors_res_json['data']['status'] == 10:
                                dic_monitors['Web'][k]['Site24x7']['state'] = site24x7_monitors_res_json['data']['status']
                else:
                    logging.error("site24x7_monitors_res_json:[%s]", site24x7_monitors_res_json)
                    logging.error("Site24x7_Payload_Monitors_Update:[%s]", Site24x7_Payload_Monitors_Update)
                if dic_monitors['Web'][k]['cybozu']['Status'] == '運用中' \
                    and any(s.startswith('Site24x7') for s in dic_monitors['Web'][k]['cybozu']['Notification']):
                    state = 0
                    if dic_monitors['Web'][k]['Site24x7']['state'] != state:
                        logging.info("Site24x7 - Monitors (Web) - Activate")
                        site24x7_monitors_res = requests.put(
                            Site24x7_Url_Base + "/monitors/activate/" + dic_monitors['Web'][k]['Site24x7']['monitor_id'],
                            headers=Site24x7_Auth_Headers)
                        site24x7_monitors_res_json = site24x7_monitors_res.json()
                        logging.debug("site24x7_monitors_res_json:[%s]", site24x7_monitors_res_json)
                        if site24x7_monitors_res_json['message'] == 'success':
                            dic_monitors['Web'][k]['Site24x7']['state'] = state
                        else:
                            logging.error("site24x7_monitors_res_json:[%s]", site24x7_monitors_res_json)
                else:
                    state = 5
                    if dic_monitors['Web'][k]['Site24x7']['state'] != state:
                        logging.info("Site24x7 - Monitors (Web) - Suspend")
                        site24x7_monitors_res = requests.put(
                            Site24x7_Url_Base + "/monitors/suspend/" + dic_monitors['Web'][k]['Site24x7']['monitor_id'],
                            headers=Site24x7_Auth_Headers)
                        site24x7_monitors_res_json = site24x7_monitors_res.json()
                        logging.debug("site24x7_monitors_res_json:[%s]", site24x7_monitors_res_json)
                        if site24x7_monitors_res_json['message'] == 'success':
                            dic_monitors['Web'][k]['Site24x7']['state'] = state
                        else:
                            logging.error("site24x7_monitors_res_json:[%s]", site24x7_monitors_res_json)
            else:
                if 'Site24x7' in dic_monitors['Web'][k] \
                    and 'type' in dic_monitors['Web'][k]['Site24x7'] \
                    and dic_monitors['Web'][k]['Site24x7']['type'] == 'URL': 
                    del_monitors.append(k)
                else:
                    pass
        return del_monitors
    
    def unsetSite24x7Monitors(del_monitors):
        """UnSet Site24x7 Monitors"""
        logging.debug("==== Site24x7 - UnSet Monitors (Web) to System ====")
        for n, k in enumerate(del_monitors):
            logging.debug("(%04d/%04d) Site24x7 - Monitors (Web) - [%s]:[%s]",
                n + 1, len(dic_monitors['Web']),
                k, dic_monitors['Web'][k])
            logging.info("Site24x7 - Monitors (Web) - Delete")
            site24x7_monitors_res = requests.delete(Site24x7_Url_Base + "/monitors/" + dic_monitors['Web'][k]['Site24x7']['monitor_id'],
                headers=Site24x7_Auth_Headers)
            site24x7_monitors_res_json = site24x7_monitors_res.json()
            logging.info("site24x7_monitors_res_json:[%s]", site24x7_monitors_res_json)
            if site24x7_monitors_res_json['message'] == 'success':
                dic_monitors['Web'][k].pop('Site24x7')
            else:
                logging.error("site24x7_monitors_res_json:[%s]", site24x7_monitors_res_json)
    
    def getStatusCakeContactGroups():
        """Get StatusCake ContactGroups"""
        logging.debug("==== StatusCake - Get ContactGroups Json ====")
        statucake_contactgroups = requests.get(StatusCake_Url_Base + '/ContactGroups?Mobiles=true',
            headers=StatusCake_Auth_Headers)
        statucake_contactgroups_json = statucake_contactgroups.json()
        logging.debug("statucake_contactgroups_json:[%s]", statucake_contactgroups_json)
        for n, k in enumerate(list(statucake_contactgroups_json)):
            logging.debug("(%04d/%04d) StatusCake - ContactGroups | " \
                "ID:[%s] Name:[%s] Mails:[%s] Mobiles:[%s]",
                n + 1, len(statucake_contactgroups_json),
                statucake_contactgroups_json[n]['ContactID'],
                statucake_contactgroups_json[n]['GroupName'],
                statucake_contactgroups_json[n]['Emails'],
                statucake_contactgroups_json[n]['Mobiles'])
            usergroup_id = statucake_contactgroups_json[n]['GroupName']
            if len(usergroup_id) == 0:
                continue
            if not usergroup_id in dic_usergroups:
                dic_usergroups[usergroup_id] = {}
            if not 'StatusCake' in dic_usergroups[usergroup_id]:
                dic_usergroups[usergroup_id]['StatusCake'] = {}
            dic_usergroups[usergroup_id]['StatusCake'][statucake_contactgroups_json[n]['ContactID']] = statucake_contactgroups_json[n]
    
    def setStatusCakeContactGroups():
        """Set StatusCake ContactGroups"""
        logging.debug("==== StatusCake - Set ContactGroups to System ====")
        for n, k in enumerate(list(dic_usergroups)):
            logging.debug("(%04d/%04d) UserGroups - [%s]:[%s]",
                n + 1, len(dic_usergroups),
                k, dic_usergroups[k])
            statucake_usergroups_res = ""
            mobiles = []
            if 'phones' in dic_usergroups[k]:
                for phone in dic_usergroups[k]['phones']:
                    phone = re.sub('[-() ]', '',phone).lstrip('0')
                    if not phone:
                        continue
                    if phone[1:2] != "0":
                        continue
                    mobiles.append("81" + phone)
            if 'cybozu' in dic_usergroups[k]:
                if 'StatusCake' in dic_usergroups[k]: 
                    for nn, kk in enumerate(list(dic_usergroups[k]['StatusCake'])):
                        if nn == 0:
                            StatusCake_Payload_ContactGroups_Update = {
                                'GroupName' : k,
                                'DesktopAlert' : 0,
                                'Email' : ','.join(sorted(dic_usergroups[k]['mails'])),
                                'Boxcar' : '',
                                'Pushover' : '',
                                'PingURL' : '',
                                'Mobile' : ",".join(sorted(mobiles)),
                                'ContactID' : kk,
                            }
                            logging.info("StatusCake - UserGroups - Update")
                            logging.debug("StatusCake_Payload_ContactGroups_Update:[%s]", StatusCake_Payload_ContactGroups_Update)
                            statucake_usergroups_res = requests.put(
                                StatusCake_Url_Base + "/ContactGroups/Update/?ContactID=" + str(dic_usergroups[k]['StatusCake'][kk]['ContactID']),
                                data=StatusCake_Payload_ContactGroups_Update, headers=StatusCake_Auth_Headers)
                            statucake_usergroups_res_json = statucake_usergroups_res.json()
                            logging.debug("statucake_usergroups_res_json:[%s]", statucake_usergroups_res_json)
                            if statucake_usergroups_res_json['Success']:
                                dic_usergroups[k]['StatusCake'][kk] = StatusCake_Payload_ContactGroups_Update
                            elif statucake_usergroups_res_json['Message'].startswith('No update made. Given:'):
                                logging.warn("statucake_usergroups_res_json:[%s]", statucake_usergroups_res_json)
                            else:
                                logging.error("statucake_usergroups_res_json:[%s]", statucake_usergroups_res_json)
                            continue
                        #
                        logging.info("StatusCake - UserGroups - Delete")
                        statucake_usergroups_res = requests.delete(
                            StatusCake_Url_Base + "/ContactGroups/Update/?ContactID=" + str(dic_usergroups[k]['StatusCake'][kk]['ContactID']),
                            headers=StatusCake_Auth_Headers)
                        statucake_usergroups_res_json = statucake_usergroups_res.json()
                        logging.debug("statucake_usergroups_res_json:[%s]", statucake_usergroups_res_json)
                        if statucake_usergroups_res_json['Success']:
                            del(dic_usergroups[k]['StatusCake'][kk])
                        else:
                            logging.error("statucake_usergroups_res_json:[%s]", statucake_usergroups_res_json)
                else:
                    logging.info("StatusCake - UserGroups - Insert")
                    StatusCake_Payload_ContactGroups_Insert = {
                        'GroupName' : k,
                        'DesktopAlert' : 0,
                        'Email' : ','.join(sorted(dic_usergroups[k]['mails'])),
                        'Boxcar' : '',
                        'Pushover' : '',
                        'PingURL' : '',
                        'Mobile' : ",".join(sorted(mobiles)),
                    }
                    logging.debug("StatusCake_Payload_ContactGroups_Insert:[%s]", StatusCake_Payload_ContactGroups_Insert)
                    statucake_usergroups_res = requests.put(StatusCake_Url_Base + '/ContactGroups/Update',
                        data=StatusCake_Payload_ContactGroups_Insert, headers=StatusCake_Auth_Headers)
                    statucake_usergroups_res_json = statucake_usergroups_res.json()
                    logging.debug("statucake_usergroups_res_json:[%s]", statucake_usergroups_res_json)
                    if statucake_usergroups_res_json['Success']:
                        dic_usergroups[k]['StatusCake'] = {}
                        dic_usergroups[k]['StatusCake'][statucake_usergroups_res_json['InsertID']] = statucake_usergroups_res_json['Data']
                        dic_usergroups[k]['StatusCake'][statucake_usergroups_res_json['InsertID']]['ContactID'] = statucake_usergroups_res_json['InsertID']
                    else:
                        logging.error("statucake_usergroups_res_json:[%s]", statucake_usergroups_res_json)
            else:
                if 'StatusCake' in dic_usergroups[k]:
                    for nn, kk in enumerate(list(dic_usergroups[k]['StatusCake'])):
                        if dic_usergroups[k]['StatusCake'][kk]['GroupName'] in {"Paused"}:
                            continue
                        logging.info("StatusCake - UserGroups - Delete")
                        statucake_usergroups_res = requests.delete(
                            StatusCake_Url_Base + "/ContactGroups/Update/?ContactID=" + str(dic_usergroups[k]['StatusCake'][kk]['ContactID']),
                            headers=StatusCake_Auth_Headers)
                        statucake_usergroups_res_json = statucake_usergroups_res.json()
                        logging.debug("statucake_usergroups_res_json:[%s]", statucake_usergroups_res_json)
                        if statucake_usergroups_res_json['Success']:
                            del(dic_usergroups[k]['StatusCake'][kk])
                        else:
                            logging.error("statucake_usergroups_res_json:[%s]", statucake_usergroups_res_json)
    
    def getStatusCakeTests():
        """Get StatusCake Tests"""
        logging.debug("==== StatusCake - Get Tests Json ====")
        statucake_tests = requests.get(StatusCake_Url_Base + '/Tests',
            headers=StatusCake_Auth_Headers)
        statucake_tests_json = statucake_tests.json()
        logging.debug("statucake_tests_json:[%s]", statucake_tests_json)
        for n, k in enumerate(list(statucake_tests_json)):
            logging.debug("(%04d/%04d) StatusCake - Tests | " \
                "ID:[%08d] Pause:[%d] Public:[%d] NmlRes:[%d] Uptime:[%03d] Status:[%s] Type:[%s] Name:[%s] Groups:[%s]",
                n + 1, len(statucake_tests_json),
                statucake_tests_json[n]['TestID'],
                statucake_tests_json[n]['Paused'],
                statucake_tests_json[n]['Public'],
                statucake_tests_json[n]['NormalisedResponse'],
                0 if statucake_tests_json[n]['Uptime'] is None else statucake_tests_json[n]['Uptime'],
                statucake_tests_json[n]['Status'],
                statucake_tests_json[n]['TestType'],
                statucake_tests_json[n]['WebsiteName'],
                ",".join(statucake_tests_json[n]['ContactGroup']))
            statucake_tests_details = requests.get(StatusCake_Url_Base + '/Tests/Details',
                params={'TestID':str(statucake_tests_json[n]['TestID'])}, headers=StatusCake_Auth_Headers)
            statucake_tests_details = statucake_tests_details.json()
            logging.debug("StatusCake - Details - [%s]", statucake_tests_details)
            logging.debug("StatusCake - Details - Name:[%s] Url:[%s]",
                statucake_tests_details['WebsiteName'],
                statucake_tests_details['URI'])
            key = "???"
            tgt = ""
            if statucake_tests_json[n]['TestType'] in {"HTTP"}:
                key = "Web"
                tgt = statucake_tests_details['URI'].rstrip('/')
            elif statucake_tests_json[n]['TestType'] in {"DNS"}:
                key = "DNS"
                tgt = statucake_tests_details['URI'].rstrip('/')
            elif statucake_tests_json[n]['TestType'] in {"HEAD", "TCP", "SMTP", "SSH", "PING", "PUSH"}:
                pass
            else:
                pass
            if len(tgt) > 0:
                if tgt in dic_monitors[key]:
                    dic_monitors[key][tgt]['StatusCake'] = statucake_tests_details
                else:
                    dic_monitors[key][tgt] = {}
                    dic_monitors[key][tgt]['StatusCake'] = statucake_tests_details
    
    def setStatusCakeTests():
        """Set StatusCake Tests"""
        logging.debug("==== StatusCake - Set Tests to System ====")
        for n, k in enumerate(list(dic_monitors['Web'])):
            logging.debug("(%04d/%04d) StatusCake - Tests - [%s]:[%s]",
                n + 1, len(dic_monitors['Web']),
                k, dic_monitors['Web'][k])
            statuscake_tests_res = ""
            if 'cybozu' in dic_monitors['Web'][k]:
                paused = True
                if dic_monitors['Web'][k]['cybozu']['Status'] == '運用中' \
                    and any(s.startswith('StatusCake') for s in dic_monitors['Web'][k]['cybozu']['Notification']):
                    paused = False
                user_group_ids = []
                for usergroup_id in dic_monitors['Web'][k]['usergroup_ids']:
                    if not usergroup_id in dic_usergroups:
                        continue
                    if not 'StatusCake' in dic_usergroups[usergroup_id]:
                        continue
                    logging.debug("dic_usergroups[usergroup_id]['StatusCake']:[%s]", dic_usergroups[usergroup_id]['StatusCake'])
                    for kk in list(dic_usergroups[usergroup_id]['StatusCake']):
                        user_group_ids.append(dic_usergroups[usergroup_id]['StatusCake'][kk]['ContactID'])
                if paused:
                    user_group_ids.append(list(dic_usergroups['Paused']['StatusCake'].keys())[0])
                if 'StatusCake' in dic_monitors['Web'][k] \
                    and 'TestType' in dic_monitors['Web'][k]['StatusCake'] \
                    and dic_monitors['Web'][k]['StatusCake']['TestType'] == 'HTTP': 
                    StatusCake_Payload_Tests_Update = ""     
                    if dic_monitors['Web'][k]['StatusCake']['URI'] != k:
                        StatusCake_Payload_Tests_Update += "&WebsiteURL=" + k
                    if dic_monitors['Web'][k]['StatusCake']['Paused'] != paused:
                        StatusCake_Payload_Tests_Update += "&Paused=" + str(int(paused))
                    contactgroup_ids = []
                    for contactgroup in dic_monitors['Web'][k]['StatusCake']['ContactGroups']:
                        contactgroup_ids.append(contactgroup['ID'])
                    if sorted(contactgroup_ids) != sorted(user_group_ids):
                        StatusCake_Payload_Tests_Update += "&ContactGroup=" + ','.join(sorted(map(str,user_group_ids)))
                    if dic_monitors['Web'][k]['StatusCake']['WebsiteName'] != k:
                        StatusCake_Payload_Tests_Update += "&WebsiteName=" + k
                    if dic_monitors['Web'][k]['StatusCake']['CheckRate'] != 300:
                        StatusCake_Payload_Tests_Update += "&CheckRate=300"
                    if dic_monitors['Web'][k]['StatusCake']['Timeout'] != 15:
                        StatusCake_Payload_Tests_Update += "&Timeout=15"
                    if dic_monitors['Web'][k]['StatusCake']['NodeLocations'] != ['JP1']:
                        StatusCake_Payload_Tests_Update += "&NodeLocations=JP1"
                    if dic_monitors['Web'][k]['StatusCake']['Tags'] != [dic_monitors['Web'][k]['cybozu']['Category']]:
                        StatusCake_Payload_Tests_Update += "&TestTags=" + dic_monitors['Web'][k]['cybozu']['Category']
                    if sorted(dic_monitors['Web'][k]['StatusCake']['StatusCodes']) != sorted(StatusCake_StatusCodes):
                        StatusCake_Payload_Tests_Update += "&StatusCodes=" + ",".join(sorted(StatusCake_StatusCodes))
                    if StatusCake_Payload_Tests_Update != "":
                        logging.info("StatusCake - Monitors (Web) - Update")
                        StatusCake_Payload_Tests_Update = "TestID=" + str(dic_monitors['Web'][k]['StatusCake']['TestID']) + StatusCake_Payload_Tests_Update
                        logging.info("StatusCake_Payload_Tests_Update:[%s]", StatusCake_Payload_Tests_Update)
                        statuscake_tests_res = requests.put(StatusCake_Url_Base + '/Tests/Update',
                            #data=StatusCake_Payload_Tests_Update,
                            data=StatusCake_Payload_Tests_Update.encode('utf-8'),
                            headers=StatusCake_Auth_Headers)
                        statuscake_tests_res_json = statuscake_tests_res.json()
                        logging.info("statuscake_tests_res_res_json:[%s]", statuscake_tests_res_json)
                        if statuscake_tests_res_json['Success'] == True:
                            dic_monitors['Web'][k]['StatusCake'] = StatusCake_Payload_Tests_Update
                        elif statuscake_tests_res_json['Message'].startswith('No data has been updated (is any data different?) Given:'):
                            logging.warn("statuscake_tests_res_res_json:[%s]", statuscake_tests_res_json)
                        else:
                            logging.error("statuscake_tests_res_res_json:[%s]", statuscake_tests_res_json)
                else:
                    StatusCake_Payload_Tests_Insert = "TestType=HTTP&CheckRate=300&Timeout=15&NodeLocations=JP1"
                    StatusCake_Payload_Tests_Insert += "&WebsiteURL=" + k
                    StatusCake_Payload_Tests_Insert += "&Paused=" + str(int(paused))
                    StatusCake_Payload_Tests_Insert += "&WebsiteName=" + k
                    StatusCake_Payload_Tests_Insert += "&TestTags=" + dic_monitors['Web'][k]['cybozu']['Category']
                    StatusCake_Payload_Tests_Insert += "&StatusCodes=" + ",".join(sorted(StatusCake_StatusCodes))
                    if len(user_group_ids) > 0:
                        StatusCake_Payload_Tests_Insert += "&ContactGroup=" + ','.join(sorted(map(str,user_group_ids)))
                    logging.info("StatusCake - Monitors (Web) - Insert")
                    logging.info("StatusCake_Payload_Tests_Insert:[%s]", StatusCake_Payload_Tests_Insert)
                    statuscake_tests_res = requests.put(StatusCake_Url_Base + '/Tests/Update',
                        data=StatusCake_Payload_Tests_Insert.encode('utf-8'),
                        headers=StatusCake_Auth_Headers)
                    statuscake_tests_res_json = statuscake_tests_res.json()
                    logging.info("statuscake_tests_res_res_json:[%s]", statuscake_tests_res_json)
                    if statuscake_tests_res_json['Success'] == True:
                        dic_monitors['Web'][k]['StatusCake'] = statuscake_tests_res_json['Data']
                        dic_monitors['Web'][k]['StatusCake']['TestID'] = statuscake_tests_res_json['InsertID']
                    else:
                        logging.error("statuscake_tests_res_res_json:[%s]", statuscake_tests_res_json)
            else:
                if 'StatusCake' in dic_monitors['Web'][k] \
                    and 'TestType' in dic_monitors['Web'][k]['StatusCake'] \
                    and dic_monitors['Web'][k]['StatusCake']['TestType'] == 'HTTP': 
                    logging.info("StatusCake - Tests (Web) - Delete")
                    statuscake_tests_res = requests.delete(StatusCake_Url_Base + '/Tests/Details',
                        params={'TestID':str(dic_monitors['Web'][k]['StatusCake']['TestID'])}, headers=StatusCake_Auth_Headers)
                    statuscake_tests_res_json = statuscake_tests_res.json()
                    logging.info("statuscake_tests_res_json:[%s]", statuscake_tests_res_json)
                    if statuscake_tests_res_json['Success'] == True:
                        dic_monitors['Web'][k].pop('StatusCake')
                    else:
                        logging.error("statuscake_tests_res_res_json:[%s]", statuscake_tests_res_json)
                else:
                    pass
    
    # ------------------------------------------------------------------------------
    # Program Start
    # ------------------------------------------------------------------------------
    if __name__ == '__main__':
    
        getCybozuUsers()
        getCybozuMonitors()
    
        getSite24x7Users()
        del_users = setSite24x7Users()
    
        getSite24x7UserGroups()
        del_usergroups = setSite24x7UserGroups()
    
        getSite24x7MonitorGroups()
        del_monitorgroups = setSite24x7MonitorGroups()
    
        getSite24x7Monitors()
        del_monitors = setSite24x7Monitors()
    
        unsetSite24x7MonitorGroups(del_monitorgroups)
        unsetSite24x7Monitors(del_monitors)
        unsetSite24x7UserGroups(del_usergroups)
        unsetSite24x7Users(del_users)
    
        getStatusCakeContactGroups()
        setStatusCakeContactGroups()
    
        getStatusCakeTests()
        setStatusCakeTests()
    
        # --------------------------------------------------------------------------
        # Mail - Create Message
        # --------------------------------------------------------------------------
        stadt = nowdt
        enddt = datetime.datetime.today()
    
        # Subject
        subject = """[%s] Set Site Monitors From Cybozu""" % (nowdt)
        logging.debug("subject : [%s]", subject)
    
        # Message
        cmd = "grep -v DEBUG " + __file__ + ".log"
        logging.debug("cmd : [%s]", cmd)
        p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        stdout_data, stderr_data = p.communicate()
        msg = """\
    
    %s - %s
    
    ----
    
    【ジョブ実行結果】
    
    %s
    """ % (stadt, enddt, str(stdout_data, encoding='utf-8'))
    
        #
        logging.debug("msg : [%s]", msg)
        #sys.exit()
    
        # --------------------------------------------------------------------------
        # Mail - Send
        # --------------------------------------------------------------------------
    
        message = MIMEText(msg, 'plain', 'utf-8')
        message['Subject'] = Header(subject, 'utf-8')
        message['From'] = MailFrom
        message['To'] = MailTo
    
        con = smtplib.SMTP(HostSMTP)
        con.set_debuglevel(True)
        con.starttls()
        con.login(LoginAccount, LoginPassword)
        con.sendmail(MailFrom, MailTo, message.as_string())
        con.close()
    
    # ------------------------------------------------------------------------------
    # Program End
    # ------------------------------------------------------------------------------
    
    logging.debug("<<<<<<<< %s End >>>>>>>>", __file__)
    
    # ---1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----

    ```
<br>
1. プログラムの動作としては、以下の様な感じです。基本的には、main 処理の流れです。
<br>
    1. cybozu から、ユーザー情報を取得する。
    2. cybozu (Kintone のサイト管理用アプリ) から、サイト情報を取得する。
    3. Site24x7 から、ユーザー情報を取得する。
    4. cybozu の情報を元に、Site24x7 へ、ユーザー情報を設定する。
    5. Site24x7 から、ユーザーグループ情報を取得する。
    6. cybozu の情報を元に、Site24x7 へ、ユーザーグループ情報を設定する。
    7. Site24x7 から、モニターグループ情報を取得する。
    8. cybozu の情報を元に、Site24x7 へ、モニターグループ情報を設定する。
    9. Site24x7 から、モニター情報を取得する。
    10. cybozu の情報を元に、Site24x7 へ、モニター情報を設定する。
    11. Site24x7 から、不要なモニターグループ情報を削除する。
    12. Site24x7 から、不要なモニター情報を削除する。
    13. Site24x7 から、不要なユーザーグループ情報を削除する。
    14. Site24x7 から、不要なユーザー情報を削除する。
    15. StatusCake から、コンタクトグループ情報を取得する。
    16. cybozu の情報を元に、StatusCake へ、コンタクトグループ情報を設定する。
    17. StatusCake から、テスト情報を取得する。
    18. cybozu の情報を元に、StatusCake へ、テスト情報を設定する。
    19. 結果をメールで通知する。
<br><br>
1. 基本的な考え方として、
<br>
    * cybozu の情報がマスタであり、各監視サービスの設定はそれに合わせる。
    * 当プログラムを日次で実行し、各監視サービスの設定を更新する。
    * 設定に変更が無い場合は、API を投げない。
<br><br>
1. 以下は、メール絡みの情報ですので、設定して下さい。
<br>
    * 当方は、587 ポートで利用していたので、それ以外のやり方だと問題出るかもしれません。

    ```bash
    # Mail
    HostSMTP = '[メールサーバ:ポート番号]'
    MailFrom = '[送信元メールアドレス]'
    MailTo = '[送信先メールアドレス]'
    LoginAccount = '[認証アカウント]'
    LoginPassword = '[認証パスワード]'
    ```
<br>
1. 以下は、cybozu 絡みの情報ですので、設定して下さい。
<br>
    * わからない場合は、以下を参照のこと。
        * [kintone REST APIの共通仕様 – cybozu developer network](https://developer.cybozu.io/hc/ja/articles/201941754)

    ```bash
    # cybozu.com
    Cybozu_Url_Base = 'https://[取得したサブドメイン].cybozu.com'
    Cybozu_Auth_Headers_UserAPI = {
        'X-Cybozu-Authorization':'[APIキー]',
        'If-Modified-Since' : 'Thu, 01 Jun 1970 00:00:00 GMT'}
    Cybozu_Auth_Headers_KintoneAPI = {
        'X-Cybozu-API-Token' : '[KintoneのAPIトークンキー]',
        'Content-Type' : 'application/json; charset=UTF-8',
        'If-Modified-Since' : 'Thu, 01 Jun 1970 00:00:00 GMT'}
    ```
<br>
1. 以下は、Site24x7 絡みの情報ですので、設定して下さい。
<br>
    * わからない場合は、以下を参照のこと。
        * [Site24x7 \| API Reference](https://www.site24x7.com/help/api/)

    ```bash
    # Site24x7
    Site24x7_Url_Base = 'https://www.site24x7.com/api'
    Site24x7_Auth_Headers = {
        'Content-Type' : 'application/json; charset=UTF-8',
        'Accept' : 'application/json; version=2.0',
        'Authorization' : '[APIキー]',
        'If-Modified-Since' : 'Thu, 01 Jun 1970 00:00:00 GMT'}
    ```
<br>
1. 以下は、StatusCake 絡みの情報ですので、設定して下さい。
<br>
    * わからない場合は、以下を参照のこと。
        * [StatusCake API Documentation](https://www.statuscake.com/api/)

    ```bash
    # StatusCake
    StatusCake_Url_Base = 'https://app.statuscake.com/API'
    StatusCake_Auth_Headers = {'API':'[APIキー]',
        'Username' : '[ユーザーID]',
        'Content-Type' : 'application/json; charset=UTF-8',
        'If-Modified-Since' : 'Thu, 01 Jun 1970 00:00:00 GMT'}
    StatusCake_StatusCodes =     ["204","205","206","303","400","401","403","404","405","406","408","410","429","444","494","495","496","499","500","501","502","504","505","506","507","511","598","599"]
    ```
<br>

1. 以下は、Site24x7 絡みの情報ですので、設定して下さい。
<br>
    * わからない場合は、以下を参照のこと。
        * [Site24x7 \| API Reference](https://www.site24x7.com/help/api/)

    ```bash
    # Site24x7
    Site24x7_Url_Base = 'https://www.site24x7.com/api'
    Site24x7_Auth_Headers = {
        'Content-Type' : 'application/json; charset=UTF-8',
        'Accept' : 'application/json; version=2.0',
        'Authorization' : '[APIキー]',
        'If-Modified-Since' : 'Thu, 01 Jun 1970 00:00:00 GMT'}
    ```
<br>
1. getCybozuMonitors の以下のステップについて、
<br>
    * Kintone アプリの ID を設定して下さい。
    * あと、フィールドコードを変更した場合は、それに合わせてこちらも変更して下さい。
        * ※ もしかしたら、他にも色々変更が必要になるかもしれません…。

    ```bash
        cybozu_monitors = requests.get(Cybozu_Url_Base + "/k/v1/records.json",
        headers=Cybozu_Auth_Headers_KintoneAPI,
        data=json.dumps({
            "app": [Kintone アプリの ID],
            "query": "$id > 0 order by $id asc limit 500",
            "fields": [
                "$id",
                "ステータス",
                "Category",
                "Title",
                "Url",
                "Notification",
                "Users"],
            "totalCount": "true"
        })
    )
    ```
<br>
1. setSite24x7Monitors の以下のステップについて、
<br>
    * デフォルトで設定するユーザーグループを設定します。
    * ID が異なることもあると思うので、ご注意を。

    ```bash
            if len(user_group_ids) == 0:
                user_group_ids = ['215015000000025003']
    ```
    * 基本的にはデフォルトの設定をそのまま設定しています。
    * ID が異なることもあると思うので、ご注意を。

    ```bash
            Site24x7_Payload_Monitors_Update = {
                "display_name": k,
                "type": 'URL',
                "website": k,
                "check_frequency": '5',
                "timeout": 15,
                "location_profile_id": "215015000004406005",
                "notification_profile_id": "215015000000025063",
                "threshold_profile_id": "215015000000025114",
                "user_group_ids": user_group_ids,
                "http_method": "G",
                "monitor_groups": monitor_groups,
                "use_ipv6": False,
                "match_case": True,
                "probe_proxy_enabled": False,     
                "auth_method": 'B',               
                "ssl_protocol": 'Auto',           
                "use_name_server": False,
            }
    ```
<br>

## ２−１．【2019.12.02 追記】

以下の記事に記載しましたが、Site24x7 の API 認証が変更になったので、

* [Site24x7 の API 認証が OAuth 2\.0 に変更されたので、アクセストークンを取得してみる。 \- Qiita](https://qiita.com/kusokamayarou/items/c02d0c376108e11d2a25)

以下の変更が必要です。

こちらの関数を追加し、
 
```python
def getSite24x7Token():
    """Set Site24x7 Token"""
    logger.debug("==== Site24x7 - Set Token Json ====")
    url = "https://accounts.zoho.com/oauth/v2/token"
    headers = {
        'Content-Type' : 'application/json; charset=UTF-8',
        'Accept' : 'application/json; version=2.0',
        'If-Modified-Since' : 'Thu, 01 Jun 1970 00:00:00 GMT'
    }
    payload = {
        'client_id': '[Client ID]',
        'client_secret': '[Client Secret]',
        'refresh_token': '[リフレッシュトークン]',
        'grant_type': 'refresh_token'
    }
    site24x7_token = requests.post(url, headers=headers, params=payload)
    logger.debug("site24x7_token:[%s]", site24x7_token)
    site24x7_token_json = site24x7_token.json()
    logger.debug("site24x7_token_json:[%s]", site24x7_token_json)
    return site24x7_token_json['access_token']
```

そして、`lambda_handler` の最初の方に、こちらの処理を追加します。

```python
        token = getSite24x7Token()
        global Site24x7_Auth_Headers
        Site24x7_Auth_Headers['Authorization'] = 'Zoho-oauthtoken ' + token
        logger.debug("Site24x7_Auth_Headers:[%s]", Site24x7_Auth_Headers)
```

# ９９．ハマりポイント

* 今回も色々ハマりました…。
<br><br>
* Site24x7 のモニター情報の登録は出来たものの、停止状態が反映されず、結構悩みました。Active / Suspend の別の API を利用いなければいけないことがわかるまで、かなりの時間をつぎ込みました。
<br><br>
* StatusCake のコンタクトグループ情報を取得するも、モバイル情報が空で返されて、これもかなり悩みました。確認したところ、セキュリティ上の観点から空にしているとのこと。変更された場合のみ、更新する仕様としているので、毎回更新されワーニングが返る様になっています…。
<br><br>
* あと、これは私が悪いんですが、StatusCake の更新 API は基本的に、パラメタ渡しなんですが、json 渡しでもいけるだろとやってみたら出来たので、そのままプログラムを組んでいたら、Insert は問題ないんですが、どうも Update がうまくいかなくて、色々悩んだ挙句、パラメタ渡しに戻すことになり、この辺でも大分時間を使ってしまいました。やはり、ドキュメントに記載されている通りにしないとダメだよね。と反省…。

# ＸＸ．まとめ

長々とプログラムを書いていますが、
とりあえずやりたいことは出来たので、ひとまず良かったです。