Open Smiley-k opened 9 months ago
@Smiley-k Have you been able to run with zulip? I'm trying mainly on mentions in tickets. Unfortunately no reaction
@Smiley-k Have you been able to run with zulip? I'm trying mainly on mentions in tickets. Unfortunately no reaction
No, I failed unfortunately, but I'm looking for solutions
I have an idea and I will test the solution with node-red
For the record, we used a mini script in Python (with a Flask container in our case) to properly add notifications in Zulip. This can be much simpler (we don't display all tickets from glpi in Zulip). I left our specific code as example.
import json
import zulip
from datetime import datetime
from bs4 import BeautifulSoup
from markdownify import markdownify as md
from typing import Any
app = Flask(__name__)
ZULIP_CHANNEL = "BSG"
GLPI_FORMS = {
"Imprimante": "content",
"Combien d'imprimantes fonctionnent encore ?": "content",
"Description du problème": ("content", "md"),
"Votre nom": "author",
"Ordinateur qui pose problème": "content",
"Déclaration du Hors Service dans Viverrin": "content",
"Type du problème": ("content", "md"),
"Nom de l'imprimante": "content",
"Où se trouve l'ordinateur ?": "content",
"Quelle page a posé problème": "content",
"Le problème porte sur": "content",
"Niveau de blocage": "content",
}
@app.route("/api", methods=["GET"])
def get_my_ip_api():
# print(request.environ)
# Are we behind RProxy ?
if 'HTTP_X_REAL_IP' in request.environ:
ip = request.environ['HTTP_X_REAL_IP']
else:
ip = request.environ['REMOTE_ADDR']
return jsonify({'ip': ip},), 200
@app.route("/glpi", methods=["POST"])
def post_zulip():
try:
data = request.data.decode('utf-8')
data_json = json.loads(data)
# Exclude SP > lecteur, + Pro
# Should we handle this ticket ?
ticket_type, ticket_category = (x.strip() for x in data_json['title'].split('-'))
print(f"{ticket_type=}, {ticket_category=}, action={data_json['action']}")
if ticket_type.strip() != 'Ticket SP' or ticket_category.strip() == 'Lecteur':
res = jsonify({'msg': 'This ticket will not be treated'})
return res, 200
soup = BeautifulSoup(data_json['content'], 'html.parser')
response = {'content': '', 'author': ''}
for i in soup.div.find_all('div'):
if len(i.contents) > 1:
# Remove question's index plus 3 last characters (' : ')
question = i.b.string.split(' ', 1)[1][:-3]
if question in GLPI_FORMS:
content = "".join([str(j) for j in list(i.children)[1:]])
if isinstance(GLPI_FORMS[question], tuple):
var_name = GLPI_FORMS[question][0]
apply_func = GLPI_FORMS[question][1]
else:
var_name = GLPI_FORMS[question]
apply_func = None
if apply_func is not None:
if apply_func == 'md':
content = md(str(content), strip=['p'])
else:
res = jsonify({'msg': f'Unknown func to apply'})
return res, 500
if var_name == 'content':
response['content'] = f"{response['content']}**{question}** : {content}\n"
else:
response[GLPI_FORMS[question]] = content
solution = None
if data_json['action'] == 'Ticket résolu':
if 'solution.description' in data_json and len(data_json['solution.description']) > 0:
soup = BeautifulSoup(data_json['solution.description'], 'html.parser')
solution = "".join([str(j).strip(" \n") for j in list(soup.children)])
else:
solution = "(Non spécifiée)"
if solution:
response['content'] = f"{response['content']}\n**Solution apportée** : {md(solution)}\n"
if data_json['author'] == '':
author = response['author'] if 'author' in response and response['author'] != '' else 'Anonyme'
else:
author = data_json['author']
stripped_id = data_json['id'].lstrip('0')
creation_date = datetime.strptime(data_json['creation'], "%d-%m-%Y %H:%M").strftime("%d/%m")
topic_name = f"{creation_date} : {ticket_category} ({stripped_id})"
client = zulip.Client(config_file="/root/.zuliprc")
if data_json['action'] == 'Nouveau ticket':
content = f"Ticket **{ticket_category}** ouvert par **{author}** ([Lien](https://support.bsg/glpi/front/ticket.form.php?id={data_json['id']}))\n{response['content']}"
elif data_json['action'] == 'Ticket résolu':
content = f"Résolution du ticket {data_json['id']} **{ticket_category}** ouvert par **{author}** ([Lien](https://support.bsg/glpi/front/ticket.form.php?id={data_json['id']}))\n{response['content']}"
elif data_json['action'] == 'Nouvel utilisateur responsable':
content = f"Le ticket {stripped_id} **{ticket_category}** ouvert par **{author}** est pris en charge par {data_json['assigntousers']} ! ([Lien](https://support.bsg/glpi/front/ticket.form.php?id={data_json['id']}))"
else:
content = f"Ticket **{ticket_category}** mis à jour ([Lien](https://support.bsg/glpi/front/ticket.form.php?id={data_json['id']}))\n{response['content']}"
data = {'type': 'stream', 'to': ZULIP_CHANNEL, 'topic': topic_name, 'content': content}
res = client.send_message(data)
if data_json['action'] == 'Ticket résolu':
# Mark topic as solved : simply prefix topic with "✔ ")
zulip_request: Dict[str, Any] = {
"anchor": "oldest",
"num_after": 1,
"num_before": 0,
"narrow": [
{"operator": "stream", "operand": ZULIP_CHANNEL},
{"operator": "search", "operand": topic_name},
]
}
result = client.get_messages(zulip_request)
data = {
"message_id": result['messages'][0]['id'],
"topic": f"✔ {topic_name}",
"propagate_mode": "change_all",
}
res = client.update_message(data)
return res, 200
except Exception as e:
print(e)
return jsonify({'msg', "Une erreur a eu lieu : voir les logs dans Wimi"}), 500
if __name__ == '__main__':
app.run()
Tried to use webhook sending to send messages to zulip (I did a migration from RC to zulip), but I found that there is no way to do the sending as zulip has a completely different integration method.
https://zulip.com/api/send-message
It would be cool if it was possible to configure webhook for zulip - is it possible to add this in a future update?