import requests from fogbugz import FogBugz import os import urllib import mimetypes import re GITEA_INSTANCE_URL = 'https://gitea.q2ii.fr' GITEA_API_TOKEN = 'e5595a8807eb22fed9663c67553609832aaac909' 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 create_gitea_issue(title, body): headers = { 'Authorization': 'token ' + GITEA_API_TOKEN } data = { 'title': title, 'body': body } url = f'{GITEA_INSTANCE_URL}/api/v1/repos/{OWNER}/{REPO}/issues' response = requests.post(url, json=data, headers=headers) if response.status_code == 201: print('Issue created successfully.') return response.json()['number'] else: print('Failed to create issue:', response.text) return None def create_gitea_comment(issue_number, comment): headers = { 'Authorization': 'token ' + GITEA_API_TOKEN } data = { 'body': comment } url = f'{GITEA_INSTANCE_URL}/api/v1/repos/{OWNER}/{REPO}/issues/{issue_number}/comments' response = requests.post(url, json=data, headers=headers) if response.status_code == 201: print('Comment created successfully.') comment_id = response.json()['id'] return comment_id else: print('Failed to create comment:', response.text) return None def upload_attachment_to_gitea_event(filename, attachment_data, comment_id): headers = { 'Authorization': 'token ' + GITEA_API_TOKEN } # Determine the content type based on the file extension content_type, _ = mimetypes.guess_type(filename) if not content_type: content_type = 'application/octet-stream' data = { 'name': filename, 'attachment': (filename, attachment_data, content_type), # Provide the content type here } url = f'{GITEA_INSTANCE_URL}/api/v1/repos/{OWNER}/{REPO}/issues/comments/{comment_id}/assets' response = requests.post(url, files=data, headers=headers) if response.status_code == 201: print('Attachment linked successfully to the event.') # Get the browser_download_url from the response download_url = response.json().get('browser_download_url') print('Download URL:', download_url) return download_url else: print('Failed to link attachment:', response.text) return None def update_gitea_comment(comment_id, updated_sHtml): headers = { 'Authorization': 'token ' + GITEA_API_TOKEN } GITEA_PATCH_URL = f'{GITEA_INSTANCE_URL}/api/v1/repos/{OWNER}/{REPO}/issues/comments/{comment_id}' patch_data = { 'body': updated_sHtml } response = requests.patch(GITEA_PATCH_URL, json=patch_data, headers=headers) if response.status_code == 200: print('Comment updated successfully.') 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(): 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 >= 242: # 93,242 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 Gitea 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_gitea_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}" comment_id = create_gitea_comment(issue_number=issue_number, comment=comment) print('comment id',comment_id); if comment_id is not None: 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_gitea_event(att.sFileName.string, attachment_data, comment_id) 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}[^>]*>' # Remplacement de tous les liens correspondant au modèle par le nouveau download_url updated_sHtml = re.sub(pattern, f'', updated_sHtml) update_gitea_comment(comment_id, updated_sHtml) fb.view(ixBug=ixBug) main()