Page History
...
Code Block | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
import com.exalate.api.domain.webhook.WebhookEntityType import com.exalate.basic.domain.hubobject.v1.BasicHubIssue import com.exalate.basic.domain.hubobject.v1.BasicHubUser import com.exalate.basic.domain.hubobject.v1.BasicHubWorkLog import com.exalate.replication.services.replication.impersonation.AuditLogService import org.slf4j.LoggerFactory import org.slf4j.Logger import play.libs.Json import scala.concurrent.Await$; import scala.concurrent.duration.Duration$; import java.text.SimpleDateFormat import java.time.Instant //Your normal Incoming Sync code //Add these functions at the end Worklogs.receive( "B0V4tQJ22LhPnznllWoT2s0N29So5", // replace the "token" with the previously generated access token replica, replica, issue, httpClient, traces, nodeHelper ) class Worklogs { static receive(String token, BasicHubIssue replica, BasicHubIssue issue, httpClient, traces, nodeHelper){ receive( token, replica, issue, httpClient, traces, nodeHelper, { BasicHubWorkLog w -> def getUser = { String key -> def localAuthor = nodeHelper.getUser(key) if (localAuthor == null) { localAuthor = new BasicHubUser() localAuthor.key = "557058:c020323a-70e4-4c07-9ccc-3ad89b1c02ec" } localAuthor } w.author = w.author ? getUser(w.author.key) : null w.updateAuthor = w.updateAuthor ? getUser(w.updateAuthor.key) : null w } ) } static receive(String token, BasicHubIssue replica, BasicHubIssue issue, httpClient, traces, nodeHelper, Closure<?> onWorklogFn){ def http = { String method, String path, Map<String, List<String>> queryParams, String body, Map<String, List<String>> headers -> def await = { future -> Await$.MODULE$.result(future, Duration$.MODULE$.apply(60, java.util.concurrent.TimeUnit.SECONDS)) } def orNull = { scala.Option<?> opt -> opt.isDefined() ? opt.get() : null } def pair = { l, r -> scala.Tuple2$.MODULE$.<?, ?>apply(l, r) } def none = { scala.Option$.MODULE$.<?> empty() } def getGeneralSettings = { def classLoader = this.getClassLoader() def gsp try { gsp = InjectorGetter.getInjector().instanceOf(classLoader.loadClass("com.exalate.api.persistence.issuetracker.jcloud.IJCloudGeneralSettingsRepository")) } catch(ClassNotFoundException exception) { gsp = InjectorGetter.getInjector().instanceOf(classLoader.loadClass("com.exalate.api.persistence.issuetracker.jcloud.IJCloudGeneralSettingsPersistence")) } def gsOpt = await(gsp.get()) def gs = orNull(gsOpt) gs } final def gs = getGeneralSettings() def removeTailingSlash = { String str -> str.trim().replace("/+\$", "") } final def tempoRestApiUrl = "https://api.tempo.io/core/3" def parseQueryString = { String string -> string.split('&').collectEntries{ param -> param.split('=', 2).collect{ URLDecoder.decode(it, 'UTF-8') } } } def parseUri parseUri = { String uri -> def parsedUri try { parsedUri = new URI(uri) if (parsedUri.scheme == 'mailto') { def schemeSpecificPartList = parsedUri.schemeSpecificPart.split('\\?', 2) def tempMailMap = parseQueryString(schemeSpecificPartList[1]) //noinspection GrUnresolvedAccess parsedUri.metaClass.mailMap = [ recipient: schemeSpecificPartList[0], cc : tempMailMap.find { //noinspection GrUnresolvedAccess it.key.toLowerCase() == 'cc' }.value, bcc : tempMailMap.find { //noinspection GrUnresolvedAccess it.key.toLowerCase() == 'bcc' }.value, subject : tempMailMap.find { //noinspection GrUnresolvedAccess it.key.toLowerCase() == 'subject' }.value, body : tempMailMap.find { //noinspection GrUnresolvedAccess it.key.toLowerCase() == 'body' }.value ] } if (parsedUri.fragment?.contains('?')) { //noinspection GrUnresolvedAccess parsedUri.metaClass.rawQuery = parsedUri.rawFragment.split('\\?')[1] //noinspection GrUnresolvedAccess parsedUri.metaClass.query = parsedUri.fragment.split('\\?')[1] //noinspection GrUnresolvedAccess parsedUri.metaClass.rawFragment = parsedUri.rawFragment.split('\\?')[0] //noinspection GrUnresolvedAccess parsedUri.metaClass.fragment = parsedUri.fragment.split('\\?')[0] } if (parsedUri.rawQuery) { //noinspection GrUnresolvedAccess parsedUri.metaClass.queryMap = parseQueryString(parsedUri.rawQuery) } else { //noinspection GrUnresolvedAccess parsedUri.metaClass.queryMap = null } //noinspection GrUnresolvedAccess if (parsedUri.queryMap) { //noinspection GrUnresolvedAccess parsedUri.queryMap.keySet().each { key -> def value = parsedUri.queryMap[key] //noinspection GrUnresolvedAccess if (value.startsWith('http') || value.startsWith('/')) { parsedUri.queryMap[key] = parseUri(value) } } } } catch (e) { throw new com.exalate.api.exception.IssueTrackerException("Parsing of URI failed: $uri\n$e", e) } parsedUri } def unsanitizedUrl = tempoRestApiUrl + path def parsedUri = parseUri(unsanitizedUrl) def embeddedQueryParams = parsedUri.queryMap def allQueryParams = embeddedQueryParams instanceof Map ? ({ def m = [:] as Map<String, List<String>>; m.putAll(embeddedQueryParams as Map<String, List<String>>) m.putAll(queryParams) })() : (queryParams ?: [:] as Map<String, List<String>>) def urlWithoutQueryParams = { String url -> URI uri = new URI(url) new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), uri.getPath(), null, uri.getFragment()).toString() } def sanitizedUrl = urlWithoutQueryParams(unsanitizedUrl) def response try { def request = httpClient .ws() .url(sanitizedUrl) .withMethod(method) if (headers != null && !headers.isEmpty()) { def scalaHeaders = scala.collection.JavaConversions.asScalaBuffer( headers.entrySet().inject([] as List<scala.Tuple2<String, String>>) { List<scala.Tuple2<String, String>> result, kv -> kv.value.each { v -> result.add(pair(kv.key, v) as scala.Tuple2<String, String>) } result } ) request = request.withHeaders(scalaHeaders) } if (!allQueryParams.isEmpty()) { def scalaQueryParams = scala.collection.JavaConversions.asScalaBuffer(queryParams.entrySet().inject([] as List<scala.Tuple2<String, String>>) { List<scala.Tuple2<String, String>> result, kv -> kv.value.each { v -> result.add(pair(kv.key, v) as scala.Tuple2<String, String>) } result }) request = request.withQueryString(scalaQueryParams) } if (body != null) { def writable = play.api.libs.ws.WSBodyWritables$.MODULE$.writeableOf_String() request = request.withBody(body, writable) } response = await(request.execute()) } catch (Exception e) { throw new com.exalate.api.exception.IssueTrackerException("Unable to perform the request $method $path, please contact Exalate Support: ".toString() + e.message, e) } if (response.status() >= 300) { throw new com.exalate.api.exception.IssueTrackerException("Failed to perform the request $method $path ${body ? "with body `$body`".toString() : ""}(status ${response.status()}), please contact Exalate Support: ".toString() + response.body()) } response.body() as String } def gsp = InjectorGetter.getInjector().instanceOf(AuditLogService.class) def js = new groovy.json.JsonSlurper() def jo = new groovy.json.JsonOutput() def listAdditionalParams = replica.customKeys."tempoWorklogParams" as Map<String, Map<String, Object>>; replica.workLogs.findAll{it.id == null}.each{ BasicHubWorkLog worklog -> def transformedWorklog try { transformedWorklog = onWorklogFn(worklog) } catch (com.exalate.api.exception.IssueTrackerException ite) { throw ite } catch (Exception e) { throw new com.exalate.api.exception.IssueTrackerException(e) } if (transformedWorklog instanceof BasicHubWorkLog) { worklog = transformedWorklog as BasicHubWorkLog } else if (transformedWorklog == null) { return } def auditLogOpt = gsp.createAuditLog(scala.Option$.MODULE$.<String>apply(issue.id as String), WebhookEntityType.WORKLOG_CREATED, worklog.getAuthor().getKey() ) def attributes = ((listAdditionalParams?.get(worklog.remoteId.toString())?.get("attributes") as Map<String, Object>)?.get("values") as List<Map<String, String>>)?.inject([]){ List<Map<String, String>>result, Map<String, String> attribute -> result.add( [ key: attribute.get("key"), value: attribute.get("value") ] ) result } ?: [] def properties = [ issueKey : issue.key, timeSpentSeconds : worklog.getTimeSpent(), billableSeconds: listAdditionalParams?.get(worklog.remoteId.toString())?.get("billableSeconds") ?: worklog.getTimeSpent(), startDate : new java.text.SimpleDateFormat("yyyy-MM-dd").format(worklog.startDate), startTime : new java.text.SimpleDateFormat("hh:mm:ss").format(worklog.startDate) ?: listAdditionalParams?.get(worklog.remoteId.toString())?.get("startTime"),//strDateSplitted[1].split("\\.")[0], description : worklog.getComment(), authorAccountId : worklog.getAuthor().getKey(), remainingEstimateSeconds: replica.remainingEstimate ?: listAdditionalParams?.get(worklog.remoteId.toString())?.get("remainingEstimateSeconds"), attributes : attributes ] def jsonTempoPost = jo.toJson(properties) def response = js.parseText(http( "POST", "/worklogs", null, jsonTempoPost, [ "Authorization":["Bearer ${token}".toString()], "Content-Type":["application/json"], ] )) println(response) gsp.updateAuditLog(scala.Option$.MODULE$.apply(auditLogOpt), issue.id as String, response["jiraWorklogId"] as String, Json.stringify(Json.toJson(response))) String localIdStr = response["tempoWorklogId"] String remoteIdStr = worklog.remoteId.toString() com.exalate.api.domain.twintrace.INonPersistentTrace trace = new com.exalate.basic.domain.BasicNonPersistentTrace() .setLocalId(localIdStr) .setRemoteId(remoteIdStr) .setType(com.exalate.api.domain.twintrace.TraceType.WORKLOG) .setAction(com.exalate.api.domain.twintrace.TraceAction.NONE) .setToSynchronize(true) traces.add(trace) } } } |
Video
Widget Connector | ||
---|---|---|
|
Questions
Questions List | ||||||||
---|---|---|---|---|---|---|---|---|
|
...