Compare commits
2 commits
2ea87072fa
...
fd401545ca
Author | SHA1 | Date | |
---|---|---|---|
fd401545ca | |||
fb7c1f7582 |
2 changed files with 83 additions and 39 deletions
65
fs2zammad
65
fs2zammad
|
@ -5,6 +5,7 @@ import json
|
|||
import os
|
||||
import pickle
|
||||
import sys
|
||||
import html2text
|
||||
|
||||
from zammad_py import ZammadAPI
|
||||
from zammad_py.api import Resource, TagList, TicketArticle
|
||||
|
@ -55,15 +56,20 @@ def get_zammad_session(impersonated_user=None):
|
|||
|
||||
def maybe_create_zammad_user(userdata, zammad_session, attr="login", default=None):
|
||||
# Map disabled users (in RT) to mock user in Zammad.
|
||||
if type(userdata) is str or "EmailAddress" not in userdata:
|
||||
if type(userdata) is str and userdata.lower() in USERMAP:
|
||||
email = userdata
|
||||
elif type(userdata) is str or "EmailAddress" not in userdata:
|
||||
userdata = {
|
||||
'EmailAddress': 'technik@ungleich.ch',
|
||||
'RealName': 'Disabled RT'
|
||||
}
|
||||
email = userdata["EmailAddress"]
|
||||
elif "EmailAddress" in userdata:
|
||||
email = userdata["EmailAddress"]
|
||||
else:
|
||||
raise ValueError("Invalid userdata")
|
||||
|
||||
email = userdata["EmailAddress"]
|
||||
lowercase_email = email.lower()
|
||||
|
||||
if lowercase_email not in USERMAP:
|
||||
kwargs = {"email": email}
|
||||
kwargs.update(config["userdata"])
|
||||
|
@ -95,6 +101,15 @@ def maybe_create_zammad_user(userdata, zammad_session, attr="login", default=Non
|
|||
|
||||
return USERMAP[lowercase_email].get(attr, default)
|
||||
|
||||
# def ensure_user_is_zammad_agent(user, zammad_session):
|
||||
# print(f"Promoting user {user} to Agent")
|
||||
# id = maybe_create_zammad_user(user, zammad_session, "id")
|
||||
# roles = maybe_create_zammad_user(user, zammad_session, "roles")
|
||||
# if "Agent" not in roles:
|
||||
# zammad_session.user.update(
|
||||
# id, {"roles": roles.append("Agent")}
|
||||
# )
|
||||
|
||||
### main logic ###
|
||||
|
||||
if not os.path.exists("rt2zammad.json"):
|
||||
|
@ -106,6 +121,7 @@ if not os.path.exists("rt2zammad.json"):
|
|||
with open("rt2zammad.json") as handle:
|
||||
config = json.load(handle)
|
||||
|
||||
h2t = html2text.HTML2Text()
|
||||
zammad = get_zammad_session()
|
||||
|
||||
os.makedirs("users", exist_ok=True)
|
||||
|
@ -188,33 +204,56 @@ for id in ticket_ids:
|
|||
|
||||
# Attachments.
|
||||
files = []
|
||||
may_contain_entry_content = None
|
||||
for a, title in entry["Attachments"]:
|
||||
with open(f"attachments/{id}/{a}", "rb") as handle:
|
||||
data = pickle.load(handle)
|
||||
|
||||
if data["Filename"] in ("", "signature.asc"):
|
||||
if data["Filename"] == "signature.asc":
|
||||
continue
|
||||
files.append(
|
||||
{
|
||||
|
||||
file_template = {
|
||||
"filename": data["Filename"],
|
||||
"data": base64.b64encode(data["Content"]).decode("utf-8"),
|
||||
"mime-type": data["ContentType"],
|
||||
}
|
||||
)
|
||||
|
||||
if data["Filename"] == '':
|
||||
if may_contain_entry_content is None:
|
||||
may_contain_entry_content = file_template
|
||||
else:
|
||||
files.append(file_template)
|
||||
|
||||
# Comment/note.
|
||||
entry_creator = entry["Creator"]
|
||||
with open(f"users/{entry_creator}", "rb") as handle:
|
||||
rt_entry_creator = pickle.load(handle)
|
||||
|
||||
zammad_creator = maybe_create_zammad_user(rt_entry_creator, zammad)
|
||||
zammad_entry_creator = maybe_create_zammad_user(rt_entry_creator, zammad)
|
||||
entry_content = entry["Content"]
|
||||
if entry_content == '' and may_contain_entry_content:
|
||||
file = may_contain_entry_content
|
||||
entry_content = base64.b64decode(file["data"]).decode("utf-8")
|
||||
if file["mime-type"]:
|
||||
entry_content = h2t.handle(entry_content)
|
||||
|
||||
zammad_entry_template = {
|
||||
"ticket_id": zammad_ticket["id"],
|
||||
"body": entry["Content"],
|
||||
"body": entry_content,
|
||||
"internal": entry["Type"] == "Comment",
|
||||
"attachments": files,
|
||||
}
|
||||
try:
|
||||
TicketArticle(get_zammad_session(zammad_creator)).create(zammad_entry_template)
|
||||
except:
|
||||
print(f"FIXME: Failed to add comment to ticket RT#{id}/Zammad#{zammad_ticket["id"]}: user permission issue?")
|
||||
entry_creator_id = maybe_create_zammad_user(zammad_entry_creator, zammad, "id")
|
||||
|
||||
# We temporarly change the ticket's creator to create a new entry
|
||||
# without giving its author 'Agent' privileges.
|
||||
restore_creator_to = None
|
||||
if entry_creator_id != zammad_ticket["customer_id"]:
|
||||
zammad_ticket = zammad.ticket.update(zammad_ticket["id"], {"customer_id": entry_creator_id})
|
||||
restore_creator_to = zammad_ticket["customer_id"]
|
||||
|
||||
print(f"-> Adding a new entry/comment to ticket {zammad_ticket["id"]} ({zammad_entry_creator})...")
|
||||
TicketArticle(get_zammad_session(zammad_entry_creator)).create(zammad_entry_template)
|
||||
|
||||
if restore_creator_to != None:
|
||||
zammad.ticket.update(zammad_ticket["id"], {"customer_id": restore_creator_to})
|
||||
|
|
57
rt2fs
57
rt2fs
|
@ -52,34 +52,39 @@ os.makedirs("attachments", exist_ok=True)
|
|||
|
||||
ticket_ids = range(config["rt_start"], config["rt_end"])
|
||||
|
||||
def dump(id):
|
||||
def dump(id, retries=3):
|
||||
print(f"Dumping RT#{id}")
|
||||
ticket_dumpfile = f"tickets/{id}"
|
||||
if not os.path.exists(ticket_dumpfile):
|
||||
ticket = rt.get_ticket(id)
|
||||
if ticket is None:
|
||||
print("Got 'None' while fetching ticket")
|
||||
os.exit(1)
|
||||
ticket["original_id"] = str(id)
|
||||
if ticket["Queue"] != 'spam':
|
||||
maybe_dump_user(rt, ticket["Creator"])
|
||||
maybe_dump_user(rt, ticket["Owner"])
|
||||
try:
|
||||
ticket_dumpfile = f"tickets/{id}"
|
||||
if not os.path.exists(ticket_dumpfile):
|
||||
ticket = rt.get_ticket(id)
|
||||
if ticket is None:
|
||||
print("Got 'None' while fetching ticket")
|
||||
os.exit(1)
|
||||
ticket["original_id"] = str(id)
|
||||
if ticket["Queue"] != 'spam':
|
||||
maybe_dump_user(rt, ticket["Creator"])
|
||||
maybe_dump_user(rt, ticket["Owner"])
|
||||
|
||||
if ticket["original_id"] != ticket["numerical_id"]:
|
||||
# Merged ticket
|
||||
history = []
|
||||
else:
|
||||
history = rt.get_history(id)
|
||||
for item in history:
|
||||
for a, title in item["Attachments"]:
|
||||
attachment = rt.get_attachment(id, a)
|
||||
os.makedirs(f"attachments/{id}", exist_ok=True)
|
||||
with open(f"attachments/{id}/{a}", "wb") as handle:
|
||||
pickle.dump(attachment, handle)
|
||||
maybe_dump_user(rt, item["Creator"])
|
||||
data = {"ticket": ticket, "history": history}
|
||||
with open(ticket_dumpfile, "wb") as handle:
|
||||
pickle.dump(data, handle)
|
||||
if ticket["original_id"] != ticket["numerical_id"]:
|
||||
# Merged ticket
|
||||
history = []
|
||||
else:
|
||||
history = rt.get_history(id)
|
||||
for item in history:
|
||||
for a, title in item["Attachments"]:
|
||||
attachment = rt.get_attachment(id, a)
|
||||
os.makedirs(f"attachments/{id}", exist_ok=True)
|
||||
with open(f"attachments/{id}/{a}", "wb") as handle:
|
||||
pickle.dump(attachment, handle)
|
||||
maybe_dump_user(rt, item["Creator"])
|
||||
data = {"ticket": ticket, "history": history}
|
||||
with open(ticket_dumpfile, "wb") as handle:
|
||||
pickle.dump(data, handle)
|
||||
except:
|
||||
print(f"Failed to dump RT#{id}.. ({retries} retries left)")
|
||||
if retries > 0:
|
||||
dump(id, retries - 1)
|
||||
|
||||
worker_count = 4
|
||||
with Pool(worker_count) as p:
|
||||
|
|
Loading…
Reference in a new issue