diff --git a/backit_gitlab.py b/backit_gitlab.py
new file mode 100644
index 0000000..604b630
--- /dev/null
+++ b/backit_gitlab.py
@@ -0,0 +1,281 @@
+import requests
+from fogbugz import FogBugz
+import os
+import urllib
+import re
+import base64
+import mimetypes
+import time
+
+GITLAB_INSTANCE_URL = 'https://gitlab.com'
+GITLAB_API_TOKEN = 'glpat-UkUD1NfVdpvyBACgzMDZ'
+GITLAB_PROJECT_ID = 39832947
+OWNER = 'fbenoist68'
+REPO = 'mobileportal'
+S_FOGBUGZ_URL = 'https://mobileretail.fogbugz.com/'
+S_EMAIL = 'frederik.benoist@gfi.fr'
+S_PASSWORD = '6brOc-gAr6'
+MAX_BUGS = 999
+
+def delete_issue(project_id, issue_iid):
+ url = f'{GITLAB_INSTANCE_URL}/api/v4/projects/{project_id}/issues/{issue_iid}'
+
+ headers = {
+ 'Private-Token': GITLAB_API_TOKEN
+ }
+
+ response = requests.delete(url, headers=headers)
+
+ if response.status_code == 204:
+ ##print(f'Issue with IID {issue_iid} deleted successfully.')
+ pass
+ else:
+ print(f'Failed to delete issue with IID {issue_iid}:', response.text)
+
+def delete_all_issues(project_id):
+ url = f'{GITLAB_INSTANCE_URL}/api/v4/projects/{project_id}/issues'
+ headers = {
+ 'Private-Token': GITLAB_API_TOKEN
+ }
+
+ remaining_issues = True
+
+ while remaining_issues:
+ response = requests.get(url, headers=headers)
+
+ if response.status_code != 200:
+ print('Failed to retrieve issues:', response.text)
+ break
+
+ issues = response.json()
+
+ if len(issues) == 0:
+ # Il n'y a plus d'issues, la suppression est terminée
+ print('All issues deleted successfully.')
+ break
+
+ for issue in issues:
+ delete_issue(project_id, issue['iid'])
+
+
+def create_gitlab_issue(title, description):
+ headers = {
+ 'Private-Token': GITLAB_API_TOKEN
+ }
+
+ data = {
+ 'title': title,
+ 'description': description
+ }
+
+ url = f'{GITLAB_INSTANCE_URL}/api/v4/projects/{OWNER}%2F{REPO}/issues'
+ response = requests.post(url, json=data, headers=headers)
+
+ if response.status_code == 201:
+ ##print('Issue created successfully.')
+ return response.json()['iid']
+ else:
+ print('Failed to create issue:', response.text)
+ return None
+
+def create_gitlab_comment(issue_number, comment):
+ headers = {
+ 'Private-Token': GITLAB_API_TOKEN
+ }
+
+ data = {
+ 'body': comment
+ }
+
+ url = f'{GITLAB_INSTANCE_URL}/api/v4/projects/{OWNER}%2F{REPO}/issues/{issue_number}/notes'
+ response = requests.post(url, json=data, headers=headers)
+
+ if response.status_code == 201:
+ ##print('Comment created successfully.')
+ return response.json()['id']
+ else:
+ print('Failed to create comment:', response.text)
+ return None
+
+def upload_attachment_to_gitlab_project(filename, attachment_data):
+ #url = f'{GITLAB_INSTANCE_URL}/api/v4/projects/{OWNER}%2F{REPO}/uploads'
+ url = f'{GITLAB_INSTANCE_URL}/api/v4/projects/{GITLAB_PROJECT_ID}/uploads'
+
+ # Encode les données binaires en base64
+ attachment_data_base64 = base64.b64encode(attachment_data).decode('utf-8')
+
+ # Determine the content type based on the file extension
+ mimetype, _ = mimetypes.guess_type(filename)
+
+ files = {
+ 'file': (filename, attachment_data, mimetype or 'application/octet-stream')
+ }
+
+ response = requests.post(url, files=files, headers={'Private-Token': GITLAB_API_TOKEN})
+
+ if response.status_code == 201:
+ ##print('Attachment uploaded successfully.')
+
+ # Obtenir l'URL de téléchargement depuis la réponse
+ download_url = response.json().get('url')
+ return download_url
+ else:
+ print('Failed to upload attachment:', response.text)
+ return None
+
+def update_gitlab_comment(comment_id, body):
+ headers = {
+ 'Private-Token': GITLAB_API_TOKEN
+ }
+
+ data = {
+ 'body': body
+ }
+
+ url = f'{GITLAB_INSTANCE_URL}/api/v4/projects/{OWNER}%2F{REPO}/issues/comments/{comment_id}'
+ response = requests.put(url, json=data, headers=headers)
+
+ if response.status_code == 200:
+ # # print('Comment updated successfully.')
+ pass
+ else:
+ print('Failed to update comment:', response.text)
+
+def get_issue_id(issue):
+ return int(issue['ixBug'])
+
+def get_event_id(event):
+ return int(event['ixBugEvent'])
+
+def main():
+ # Utilisation de la fonction pour supprimer toutes les issues d'un projet spécifique
+ # delete_all_issues(GITLAB_PROJECT_ID)
+
+ fb = FogBugz(S_FOGBUGZ_URL)
+ fb.logon(S_EMAIL, S_PASSWORD)
+
+ resp = fb.search(q='type:"Cases"', cols='ixBug', max=MAX_BUGS)
+
+ for case in sorted(resp.cases.findAll('case'), key=get_issue_id, reverse=False):
+ ixBug = int(case['ixBug'])
+ if ixBug >= 590:
+ time.sleep(1) # Pause d'une seconde
+
+ print(ixBug)
+
+ respBug = fb.search(q='%s' % ixBug, cols='sTitle,sPersonAssignedTo,sProject,sArea,sCategory,sPriority,events')
+ xmlBug = respBug.cases.findAll('case')[0]
+
+ BACKUP_DIR = '/Users/fbenoist68/Code/python/fogbugz/fogbackup'
+ BACKUP_DIR += '/' + xmlBug.sProject.string if xmlBug.sProject.string else ''
+
+ if not os.path.exists(BACKUP_DIR):
+ os.makedirs(BACKUP_DIR)
+
+ BACKUP_DIR += '/' + str(xmlBug['ixBug'])
+
+ if not os.path.exists(BACKUP_DIR):
+ os.makedirs(BACKUP_DIR)
+
+ # Create GitLab issue
+ issue_title = f"[FogBugz #{ixBug}] {xmlBug.sTitle.string if xmlBug.sTitle.string else ''}"
+ issue_body = f"Assigned To: {xmlBug.sPersonAssignedTo.string}\n"
+ issue_body += f"Project: {xmlBug.sProject.string}\n"
+ issue_body += f"Area: {xmlBug.sArea.string}\n"
+ issue_body += f"Category: {xmlBug.sCategory.string}\n"
+ issue_body += f"Priority: {xmlBug.sPriority.string}\n"
+
+ issue_number = create_gitlab_issue(issue_title, issue_body)
+
+ if issue_number is not None:
+ # Create Gitea comment for each event in reverse !!
+ for event in sorted(xmlBug.events.findAll('event'), key=get_event_id, reverse=True):
+ bugEvent = {}
+ bugEvent['ixBugEvent'] = int(event['ixBugEvent'])
+ bugEvent['sVerb'] = event.sVerb.string if event.sVerb.string else ''
+ bugEvent['dt'] = event.dt.string if event.dt.string else ''
+ bugEvent['s'] = event.s.string if event.s.string else ''
+ bugEvent['sChanges'] = event.sChanges.string if event.sChanges.string else ''
+ bugEvent['evtDescription'] = event.evtDescription.string if event.evtDescription.string else ''
+ bugEvent['sPerson'] = event.sPerson.string if event.sPerson.string else ''
+
+ if event.s and event.s.string:
+ bugEvent['s'] = event.s.string.encode('ascii', 'ignore').decode('utf-8')
+ else:
+ bugEvent['s'] = ''
+
+ if event.sHtml and event.sHtml.string:
+ bugEvent['sHtml'] = event.sHtml.string.encode('ascii', 'ignore').decode('utf-8')
+ else:
+ bugEvent['sHtml'] = ''
+
+ comment = f"Event ID: {bugEvent['ixBugEvent']}\n"
+ comment += f"Date: {bugEvent['dt']}\n"
+ comment += f"Person: {bugEvent['sPerson']}\n"
+ comment += f"Description: {bugEvent['evtDescription']}\n\n\n"
+
+ # Afficher sHtml s'il n'est pas vide, sinon afficher s
+ content = bugEvent['sHtml'] if bugEvent['sHtml'] else bugEvent['s']
+ comment += f"{content}"
+
+ new_links = {}
+
+ for att in event.rgAttachments:
+ # # print('Downloading attachment: ' + att.sFileName.string)
+ str1 = att.sURL.string
+ str2 = 'ixAttachment='
+ loc1 = str1.find(str2) + len(str2)
+ loc2 = str1.find('&sFileName')
+
+ str3 = ';sFileName='
+ loc3 = str1.find(str3) + len(str3)
+ loc4 = str1.find('&sTicket')
+
+ theURL = S_FOGBUGZ_URL # + att.sURL.string
+ theURL += 'default.asp?'
+ theURL += 'ixAttachment=' + str1[loc1:loc2]
+ theURL += '&pg=pgDownload&pgType=pgFile&sFilename=' + str1[loc3:loc4]
+ theURL += '&token=rnl0t87rp34rfg6q0u0rgbhe85v5r8'
+
+ # fix the replace
+ newFileName = att.sFileName.string.replace('/', '')
+ newFileName = newFileName.replace(':', '')
+ newFileName = BACKUP_DIR + '/' + newFileName
+ # # print(newFileName)
+ urllib.request.urlretrieve(theURL, newFileName)
+
+ with open(newFileName, 'rb') as attachment_file:
+ attachment_data = attachment_file.read()
+
+ # # print('Uploading screenshot:', att.sFileName.string)
+ download_url = upload_attachment_to_gitlab_project(att.sFileName.string, attachment_data)
+
+ if download_url:
+ # Stocker le nouveau lien avec l'ID de l'attachement comme clé
+ new_links[str1[loc1:loc2]] = download_url
+
+ if new_links:
+ # Remplacer les liens d'attachement dans sHtml avec les nouvelles URLs
+ updated_sHtml = comment
+
+ for att_id, download_url in new_links.items():
+ # Utilisation d'une expression régulière pour trouver les liens img avec ixAttachment=574
+ pattern = fr'
]*?ixAttachment={att_id}[^>]*>'
+
+ # Testez si le motif correspond à la chaîne de texte
+ match = re.search(pattern, updated_sHtml)
+
+ # Remplacement de tous les liens correspondant au modèle par le nouveau download_url
+ if match:
+ updated_sHtml = re.sub(pattern, f'
', updated_sHtml)
+ else:
+ updated_sHtml += f'\n
'
+
+ comment_id = create_gitlab_comment(issue_number=issue_number, comment=updated_sHtml)
+ else:
+ comment_id = create_gitlab_comment(issue_number=issue_number, comment=comment)
+
+ # # print('comment id',comment_id);
+
+ fb.view(ixBug=ixBug)
+main()
\ No newline at end of file