From 2c99214db5a9b5b483de2e6c3ff6255122d47210 Mon Sep 17 00:00:00 2001 From: linuro Date: Mon, 8 Jun 2020 03:22:39 +0200 Subject: [PATCH] Initial Commit --- main.py | 171 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100755 main.py diff --git a/main.py b/main.py new file mode 100755 index 0000000..101e276 --- /dev/null +++ b/main.py @@ -0,0 +1,171 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# assemble the undead +# +# This is a script that serves the purpose of creating a wikipage and +# send out a mail, when there are issues in redmine with a certain +# status. It's supposed to be running as a crownjob. +# +# Copyright 2020 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. +# +# + +import sys, requests, datetime,smtplib +from email.mime.text import MIMEText + +# Redmine config +redmine_url = 'https://tickets.zom.bi' +redmine_api_key = '' + +## Mediawiki config +mediawiki_url = 'https://w.zom.bi' +# those should be Bot credentials, that can be created on Special:BotPasswords +mediawiki_username = 'Assemblybot@assemblybot' +mediawiki_botpassword='' + +# smtp config +smtp_host = 'mail.zom.bi' +smtp_port = 465 +smtp_from = 'assembly_noreply@zom.bi' +smtp_to = [''] +smtp_user = 'assemblybot' +smtp_password = '' +mail_subject = '☣ The undead assemble' +mail_header = "Greetings fellow undead,\nthere are some open \ +issues that require a decision from an assembly. You'll find a list \ +of said issues at the end of this mail. If you wonna know more about \ +those topics, please head to our issue tracker at https://tickets.zom.bi\ +\n----\n\n\n" + +mail_footer = "\n----\n beep, boop. I'm a bot.\n If you wonna\ +complain about me, write a mail to cpp or create a ticket at https://tickets.zom.bi" + +def main(args): + + assembly_date = str(datetime.date.today() +\ + datetime.timedelta((6-datetime.date.today().weekday()) % 7)) + requires_assembly = redmine_get_requires_assembly_id() + log(1,"Assembly topics:\n") + issues = redmine_get_issues(requires_assembly) + if not issues: + # do nothing, if there are no issues requiring an assembly. + log(1,"No issue requires an assembly.\n exiting.") + return 0 + mediawiki_page = {'title': 'Zombi:Assembly '+assembly_date, 'content':'{{plenum|Datum=' + assembly_date + '}}'} + mediawiki_page['content'] = '=Issues from redmine that require an assembly=\n' + for issue in issues: + # Append every issue to the page content + log(1,issue['subject']) + mediawiki_page['content']= mediawiki_page['content'] + '==' +\ + issue["subject"]+ '==\n\n' + 'Author: ' +\ + issue['author']['name'] + '\n\n' + issue['description'] + '\n' + log(1,'') + if '--no-wiki' in args: + log(1,"'--no-wiki' argument given, so no wiki page has been created.") + else: + mediawiki_session = mediawiki_login() + mediawiki_create(mediawiki_session, mediawiki_page) + + # Send out the mail + if '--no-mail' in args: + log(1,"'--no-mail' argument given, so no mails have been sent.") + else: + smtp_server = smtplib.SMTP_SSL(host=smtp_host,port=smtp_port) + if loglevel == 2: + smtp_server.set_debuglevel(1) + smtp_server.connect(host=smtp_host) + smtp_server.login(user=smtp_user,password=smtp_password) + mail_message = MIMEText(mail_header + mediawiki_page['content'] + mail_footer) + mail_message['Subject'] = mail_subject + mail_message['From'] = smtp_from + mail_message['To'] = None + smtp_server.sendmail(from_addr=smtp_from,to_addrs=smtp_to,msg=mail_message.as_string()) + smtp_server.quit() + return 0 + +def redmine_request(path): + request = requests.get(redmine_url + path, + headers={ + 'X-Redmine-API-Key': redmine_api_key + } + ) + return request.json() + +def redmine_get_requires_assembly_id(): + data = redmine_request('/issue_statuses.json') + requires_assembly = next(filter(lambda x: x['name'] == 'Requires Assembly',data['issue_statuses']))['id'] + return requires_assembly + +def redmine_get_issues(state): + tickets = redmine_request('/issues.json?status_id=' + str(state)) + return tickets['issues'] + +def mediawiki_login(): + log(2,"Logging into mediawiki") + s = requests.Session() + t_request = s.post(mediawiki_url + + "/api.php?action=query&format=json&meta=tokens&type=login") + token = t_request.json()["query"]["tokens"]["logintoken"] + response= s.post(mediawiki_url + '/api.php?action=login&format=json', + data={ + 'lgname': mediawiki_username, + 'lgpassword': mediawiki_botpassword, + 'lgtoken': token + } + ).json() + if 'error' in response: + log(0,'Logging into mediawiki failed, errorcode: '+ response['error']['code']) + raise ValueError(response["error"]) + else: + log(2,response['login']['result']) + return s +def mediawiki_create(s,page): + log(2,'Creating Wiki page "'+ page['title'] + '"') + t_request = s.post(mediawiki_url + + '/api.php?action=query&format=json&meta=tokens') + token = t_request.json()["query"]["tokens"]["csrftoken"] + response = s.post(mediawiki_url + '/api.php?action=edit&format=json' + '&title=' + page['title'] + '&text=', + data = { + 'token': token, + 'text' : page['content'] + } + ).json() + if 'error' in response: + log(0,'Creating page failed, errorcode: '+ response['error']['code']) + raise ValueError(response["error"]) + else: + log(2,response['edit']['result']) + return 0 + +def log(l,log_message): + # 0 - only print errors (-q) + # 1 - normal operation + # 2 - print everything + + if l<=loglevel: + print(log_message) + +if __name__ == '__main__': + if '-q' in sys.argv or '--quiet' in sys.argv: + loglevel = 0 + elif '-v' in sys.argv or '--verbose' in sys.argv: + loglevel = 2 + else: + loglevel = 1 + sys.exit(main(sys.argv))