Checkpoint: 4/9/2019
[margebot.git] / plugins / marge.py
index 227e16a..2764209 100755 (executable)
@@ -1,8 +1,8 @@
 """
 Margebot: A Errbot Plugin for Gitlab MR reminders
 """
+import re
 from datetime import datetime, timezone
-from time import sleep
 from dateutil import parser
 from dateutil.tz import tzutc
 from dateutil.relativedelta import relativedelta
@@ -10,51 +10,6 @@ from errbot import BotPlugin, arg_botcmd, botcmd, re_botcmd, webhook
 from errbot.templating import tenv
 from errcron.bot import CrontabMixin
 import gitlab
-import requests
-
-
-class MargeGitlab(gitlab.Gitlab):
-    """
-    Subclass gitlab.Gitlab so extra_data args can be added
-    to the addprojecthook() and editprojecthook() methods
-    """
-
-    def __init__(self, host, token="", oauth_token="", verify_ssl=True):
-        super().__init__(host, token, oauth_token, verify_ssl)
-
-    def addprojecthook_extra(self, project_id, url, push=False, issues=False, merge_requests=False, tag_push=False, extra_data=None):
-        """
-        A copy parent addprojecthook with an extra_data field
-        """
-        data = {"id": project_id, "url": url}
-        if extra_data:
-            for ed_key, ed_value in extra_data.items():
-                data[ed_key] = ed_value
-        data['push_events'] = int(bool(push))
-        data['issues_events'] = int(bool(issues))
-        data['merge_requests_events'] = int(bool(merge_requests))
-        data['tag_push_events'] = int(bool(tag_push))
-        request = requests.post("{0}/{1}/hooks".format(self.projects_url, project_id),
-                                headers=self.headers, data=data, verify=self.verify_ssl)
-        if request.status_code == 201:
-            return request.json()
-        return False
-
-    def editprojecthook_extra(self, project_id, hook_id, url, push=False, issues=False, merge_requests=False, tag_push=False, extra_data=None):
-        """
-        A copy of the parent editprojecthook with an extra_data field
-        """
-        data = {"id": project_id, "hook_id": hook_id, "url": url}
-        if extra_data:
-            for ed_key, ed_value in extra_data.items():
-                data[ed_key] = ed_value
-        data['push_events'] = int(bool(push))
-        data['issues_events'] = int(bool(issues))
-        data['merge_requests_events'] = int(bool(merge_requests))
-        data['tag_push_events'] = int(bool(tag_push))
-        request = requests.put("{0}/{1}/hooks/{2}".format(self.projects_url, project_id, hook_id),
-                               headers=self.headers, data=data, verify=self.verify_ssl)
-        return request.status_code == 200
 
 
 def deltastr(any_delta):
@@ -143,8 +98,7 @@ class Marge(BotPlugin, CrontabMixin):
         Marge.CRONTAB = ['{} .crontab_hook'.format(self.config['CRONTAB'])]
         gitlab_auth_token = self.config['GITLAB_ADMIN_TOKEN']
         verify_ssl = self.config['VERIFY_SSL']
-        # self.gitlab = gitlab.Gitlab(self.git_host, gitlab_auth_token, verify_ssl=verify_ssl)
-        self.gitlab = MargeGitlab(self.git_host, gitlab_auth_token, verify_ssl=verify_ssl)
+        self.gitlab = gitlab.Gitlab(self.git_host, gitlab_auth_token, verify_ssl=verify_ssl)
         self.activate_crontab()
 
         self.soak_delta = relativedelta(hours=self.config['CRONTAB_SOAK_HOURS'])
@@ -166,7 +120,7 @@ class Marge(BotPlugin, CrontabMixin):
         """
 
         self.log.info("webhook: request: {}, rooms: {}".format(request, rooms))
-        self.log.info("state: {}".format(request['object_attributes']['state']))
+        self.log.info("state: {}".format(request['object_attributes']['state']))
 
         # verify it's a merge request
         if request['object_kind'] != 'merge_request':
@@ -410,16 +364,11 @@ class Marge(BotPlugin, CrontabMixin):
 
         return {'sender': sender, 'msg_list': msg_list}
 
-    # -----------------------------------------------------------
-    # webhook maintenance commands
-
-    @arg_botcmd('rooms', type=str)
-    @arg_botcmd('repo', type=str)
+    @arg_botcmd('rooms', type=str, help="Comma-separated room list without @conference-room suffix")
+    @arg_botcmd('repo', type=str, help="repo to start watching for MRs in NAMESPACE/PROJECT_NAME format")
     def watchrepo(self, msg, repo, rooms):
         """
         Add the margebot webhook to a repo, and prepopulate any open MRs in the repo with margebot
-        args: repo: gitlab repo name in the 'NAMESPACE/PROJECT_NAME' format
-              rooms:  comma separates list of rooms to notify when the webhook triggers
         """
         self.log.info("msg={}".format(msg))
         self.log.info("repo={}".format(repo))
@@ -440,13 +389,14 @@ class Marge(BotPlugin, CrontabMixin):
         # If no hooks, will it return False or [] ?
         marge_hook = None
         hooks = self.gitlab.getprojecthooks(target_project_id)
-        if not hooks:
+        self.log.error("hooks = {}".format(hooks))
+        if hooks is False:
             msg = "Couldn't find {} hooks".format(repo)
             self.log.error("watchrepo: {}".format(msg))
             return msg
         else:
             for a_hook in hooks:
-                self.log.info('a_hook: {}'.format(a_hook))
+                self.log.info('a_hook: {} {}'.format(a_hook, self.webhook_url))
                 if a_hook['merge_requests_events'] and a_hook['url'].startswith(self.webhook_url):
                     marge_hook = a_hook
                     break
@@ -461,12 +411,12 @@ class Marge(BotPlugin, CrontabMixin):
                 self.log.info('watchrepo: {}'.format(msg))
                 return msg
             else:
-                hook_updated = self.gitlab.editprojecthook_extra(target_project_id, marge_hook['id'], url, merge_requests=True, extra_data={'enable_ssl_verification': False})
+                hook_updated = self.gitlab.editprojecthook(target_project_id, marge_hook['id'], url, merge_requests=True)
                 s_watch_msg = "Updating room list for {} MRs from {} to {}".format(repo, old_rooms, rooms)
                 s_action = "update"
         else:
-            hook_updated = self.gitlab.addprojecthook_extra(target_project_id, url, merge_requests=True, extra_data={'enable_ssl_verification': False})
-            s_watch_msg = "Now watching for new MRs in the {} repo to the {} roomi(s)".format(repo, rooms)
+            hook_updated = self.gitlab.addprojecthook(target_project_id, url, merge_requests=True)
+            s_watch_msg = "Now watching for new MRs in the {} repo to the {} room(s)".format(repo, rooms)
             s_action = "add"
 
         if not hook_updated:
@@ -495,7 +445,7 @@ class Marge(BotPlugin, CrontabMixin):
             for state in ['opened', 'reopened']:
                 page = 1
                 mr_list = self.gitlab.getmergerequests(target_project_id, page=page, per_page=100, state=state)
-                while not mr_list and mr_list != []:
+                while (mr_list is not False) and (mr_list != []):
                     for an_mr in mr_list:
                         mr_count += 1
                         self.log.info('watchrepo: an_mr WATS THE ID\n{}'.format(an_mr))
@@ -517,34 +467,40 @@ class Marge(BotPlugin, CrontabMixin):
         return "{}\n{}".format(s_watch_msg, mr_msg)
 
     # pragma pylint: disable=unused-argument
-    @botcmd()
-    def hello(self, msg, args):
-        """
-        A simple command to check if the bot is responding
-        """
-        return "Hi there"
 
-    @botcmd()
-    def xyzzy(self, msg, args):
-        """
-        Don't call this command...
-        """
-        yield "/me whispers \"All open MRs have been merged into master.\""
-        sleep(5)
-        yield "(just kidding)"
-
-    @re_botcmd(pattern=r"I blame [Mm]arge([Bb]ot)?")
+    @re_botcmd(pattern=r"I blame marge(bot)?", prefixed=False, flags=re.IGNORECASE)
     def dont_blame_margebot(self, msg, match):
         """
         margebot is innocent.
         """
-        yield "(」゚ロ゚)」NOOOooooo say it ain't so."
+        yield u"(\u300D\uFF9F\uFF9B\uFF9F)\uFF63NOOOooooo say it ain't so."
 
-    @re_botcmd(pattern=r"good bot")
+    @re_botcmd(pattern=r"good bot", prefixed=False, flags=re.IGNORECASE)
     def best_bot(self, msg, match):
         """
         margebot is the best.
         """
         yield "Best bot"
 
+    @re_botcmd(pattern=r"magfest", prefixed=False, flags=re.IGNORECASE)
+    def margefest(self, msg, args):
+        """
+        margefest4ever
+        """
+        return "More like MargeFest, amirite ?"
+
+    @re_botcmd(pattern=r"margebot sucks", prefixed=False, flags=re.IGNORECASE)
+    def margebot_sucks(self, msg, args):
+        """
+        Bring it up with the committee
+        """
+        return "Bring it up with the Margebot steering committee."
+
+    @re_botcmd(pattern=r".*", prefixed=True)
+    def catchall(self, msg, args):
+        """
+        Don't have the bot complain about unknown commands if the first word in a msg is its name
+        """
+        return
+
     # pragma pylint: enable=unused-argument