Commit 8809db87 authored by 汪洋's avatar 汪洋

初版完成,哈哈

parent f6f736d7
......@@ -26,6 +26,7 @@
D3E5960F222FBDBC004DCC62 /* 获取EditIssue.md in Resources */ = {isa = PBXBuildFile; fileRef = D3E5960E222FBDBB004DCC62 /* 获取EditIssue.md */; };
D3E59611222FBDDD004DCC62 /* 修改Issue.md in Resources */ = {isa = PBXBuildFile; fileRef = D3E59610222FBDDD004DCC62 /* 修改Issue.md */; };
D3E596132233D22D004DCC62 /* 获取迭代列表.md in Resources */ = {isa = PBXBuildFile; fileRef = D3E596122233D22D004DCC62 /* 获取迭代列表.md */; };
D3E5961522366176004DCC62 /* 创建subtask获取信息.md in Resources */ = {isa = PBXBuildFile; fileRef = D3E5961422366176004DCC62 /* 创建subtask获取信息.md */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
......@@ -53,6 +54,7 @@
D3E5960E222FBDBB004DCC62 /* 获取EditIssue.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "获取EditIssue.md"; sourceTree = "<group>"; };
D3E59610222FBDDD004DCC62 /* 修改Issue.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "修改Issue.md"; sourceTree = "<group>"; };
D3E596122233D22D004DCC62 /* 获取迭代列表.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "获取迭代列表.md"; sourceTree = "<group>"; };
D3E5961422366176004DCC62 /* 创建subtask获取信息.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "创建subtask获取信息.md"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
......@@ -124,6 +126,7 @@
D3E5960E222FBDBB004DCC62 /* 获取EditIssue.md */,
D3E59610222FBDDD004DCC62 /* 修改Issue.md */,
D3E596122233D22D004DCC62 /* 获取迭代列表.md */,
D3E5961422366176004DCC62 /* 创建subtask获取信息.md */,
);
path = "代码阅读";
sourceTree = "<group>";
......@@ -207,6 +210,7 @@
D3E596032227B5CD004DCC62 /* 创建story.md in Resources */,
D3E59611222FBDDD004DCC62 /* 修改Issue.md in Resources */,
D3E595E322240DCF004DCC62 /* Assets.xcassets in Resources */,
D3E5961522366176004DCC62 /* 创建subtask获取信息.md in Resources */,
D3E595E622240DCF004DCC62 /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
......
......@@ -2,4 +2,22 @@
<Bucket
type = "0"
version = "2.0">
<Breakpoints>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "AutoJira/Page.swift"
timestampString = "574068187.2949851"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "89"
endingLineNumber = "89"
landmarkName = "getUser(tr:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
</Breakpoints>
</Bucket>
<?xml version="1.0" encoding="UTF-8"?>
<VariablesViewState
version = "1.0">
<ContextStates>
<ContextState
contextName = "Page.getUser(tr:):Page.swift">
</ContextState>
<ContextState
contextName = "Page.init(page:):Page.swift">
<PersistentStrings>
<PersistentString
value = "tr.xpath(&quot;td//div//p//a&quot;)">
</PersistentString>
<PersistentString
value = "tr.at_xpath(&quot;th&quot;)!.innerHTML!">
</PersistentString>
<PersistentString
value = "tr.toHTML!">
</PersistentString>
</PersistentStrings>
</ContextState>
<ContextState
contextName = "static Story.quickCreateIssue():Story.swift">
</ContextState>
<ContextState
contextName = "URLRequest.sync(with:):Utils.swift">
</ContextState>
<ContextState
contextName = "closure #1 in static RepeatedWork.fuckit(on:):RepeatdWork.swift">
</ContextState>
<ContextState
contextName = "Sprint.init(dic:):ViewController.swift">
</ContextState>
<ContextState
contextName = "static RepeatedWork.doTheRepeatedWork(_:):RepeatdWork.swift">
</ContextState>
<ContextState
contextName = "closure #1 in ViewController.login():ViewController.swift">
</ContextState>
<ContextState
contextName = "ViewController.viewDidLoad():ViewController.swift">
</ContextState>
</ContextStates>
</VariablesViewState>
......@@ -10,6 +10,10 @@ import Cocoa
import Kanna
import ReactiveSwift
struct People {
var name: String
var id: String
}
/*
可以使用html属性进一步来查看当前所代码的html代码。
*/
......@@ -21,9 +25,9 @@ class Page: NSObject {
var pageUrl: String = ""
let session = URLSession.shared
var html: HTMLDocument?
var fo: String = ""
var testers: [String] = []
var developers: [String] = []
var fo: People?
// developers包括各端开发人员,测试人员
var developers: [People] = []
convenience init(page: Kanna.XMLElement) {
self.init()
......@@ -40,48 +44,49 @@ class Page: NSObject {
}
// 核心是得到developers,其它都是错误处理
if let developersHtml = html?.xpath("//*[@id=\"main-content\"]/div[1]/div/table/tbody/tr[2]/td/div/p/a") {
for developer in developersHtml.makeIterator() {
if let name = developer["data-username"] {
developers.append(name)
} else {
if developer.toHTML != nil {
Log.append("\(developer.toHTML!) 没有成功解析")
} else {
Log.append("\(developer)没有成功解析")
}
}
}
guard let tableTr = html?.xpath("//*[@id=\"main-content\"]/div[1]/div/table/tbody/tr") else {
Log.append("没有得到需求文档的table")
return
}
// 得到FO
if let foHtml = html?.at_xpath("//*[@id=\"main-content\"]/div[1]/div/table/tbody/tr[6]/td/div/p/span/a") {
if let name = foHtml["data-username"] {
fo = name
} else {
if foHtml.toHTML != nil {
Log.append("\(foHtml.toHTML!) 没有成功解析")
// 循环table中的每一行,如果该行是FO或者开发这一类的,就进行人员解析
for tr in tableTr.makeIterator() {
guard let th = tr.at_xpath("th")?.innerHTML else {
Log.append("\(tr.toHTML!) table tr/th中没有span")
continue
}
if th.contains("FO") {
if let user = getUser(tr: tr).first {
fo = user
} else {
Log.append("\(foHtml)没有成功解析")
Log.append("\(tr.toHTML!) FO 没有正确生成")
continue
}
} else if th.contains("测试") || th.contains("开发") || th.contains("数据") {
developers.append(contentsOf: getUser(tr: tr))
}
}
// 得到测试人员
if let users = html?.xpath("//*[@id=\"main-content\"]/div[1]/div/table/tbody/tr[8]/td/div/p/a") {
for testerHtml in users.makeIterator() {
if let name = testerHtml["data-username"] {
developers.append(name)
} else {
if testerHtml.toHTML != nil {
Log.append("\(testerHtml.toHTML!) 没有成功解析")
} else {
Log.append("\(testerHtml)没有成功解析")
}
Log.append("成功得到所有人员")
}
// 从table的行中解析人员
func getUser(tr: Kanna.XMLElement) -> [People] {
let userHtmls = tr.xpath("td//a")
var users: [People] = []
for html in userHtmls.makeIterator() {
if let name_id = html["data-username"], let name = html.innerHTML {
users.append(People(name: name, id: name_id))
} else {
if html.toHTML != nil {
Log.append("\(html.toHTML!) 没有成功解析")
continue
}
Log.append("\(html)没有成功解析")
}
}
return users
}
func isValide() -> Bool {
......
......@@ -42,7 +42,7 @@ struct RepeatedWork {
// 期望在这儿只得到主需求的列表
// 但是doc.xpath("//td[@data-content-id]")仍然得到了所有的
let obj = doc.xpath("//td[@data-content-id]")
let obj = doc.xpath("//*[@id=\"main-content\"]/div[2]/table/tbody//td[@data-content-id]")
if obj.count == 0 {
Log.append("没有需要列表\nhtml")
return
......@@ -52,21 +52,24 @@ struct RepeatedWork {
let page = Page(page: node)
if !page.isValide() {
Log.append("page 信息有问题")
Log.append("\(node.toHTML!) page 信息有问题")
continue
}
if let story = Story.createStory(with: page.title) {
page.story = story
} else {
Log.append("story创建出错")
Log.append("\(node.toHTML!) story创建出错")
continue
}
page.story.connect(to: page.pageId, with: page.lastFetchTime)
page.story.editStoryInfo(assignee: page.fo)
// Story.createSubtask(page: page)
if let foId = page.fo?.id {
page.story.editStoryInfo(assignee: foId)
} else {
Log.append("\(node.toHTML!) 没有正确修改story")
}
page.story.createSubtask(page: page)
}
}
}
......@@ -14,6 +14,9 @@ class Story: NSObject {
var storyKey: String = ""
var storyId: String = ""
var summary: String = ""
var pid: String = ""
var subtask_atl_token = ""
var subtask_formToken = ""
convenience init(storyKey: String, storyId: String) {
self.init()
......@@ -56,8 +59,6 @@ class Story: NSObject {
}
/// 关联文档与story
///
/// - Parameter page: Page实例
func connect(to pageId: String, with pageLastFetchTime: String) {
Log.append("关联story与wiki")
let url = URL(string: "http://wiki.wanmeizhensuo.com/rest/highlighting/1.0/insert-storage-fragment")!
......@@ -86,14 +87,10 @@ class Story: NSObject {
}
}
/// 修改story的“指派人”
/// 修改story所在的sprint
/// - Parameter page: page实例
func editStoryInfo(assignee: String) {
Log.append("编辑story的assign与sprint")
// assign
// sprint
let url = URL(string: "http://jira.wanmeizhensuo.com/secure/QuickEditIssue.jspa?issueId=\(storyId)&decorator=none")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
......@@ -115,6 +112,7 @@ class Story: NSObject {
}
}
/// 先模拟点击修改,以获取formToken、atl_token
func getEditIssueFormdata(assignee: String) -> String? {
let url = URL(string: "http://jira.wanmeizhensuo.com/secure/QuickEditIssue!default.jspa?issueId=\(self.storyId)&decorator=none")!
var request = URLRequest(url: url)
......@@ -133,30 +131,113 @@ class Story: NSObject {
return nil
}
guard let formToken = json!["formToken"] else {
guard let formToken = json!["formToken"] as? String else {
Log.append("formToken出错")
return nil
}
guard let atl_token = json!["atl_token"] else {
guard let atl_token = json!["atl_token"] as? String else {
Log.append("atl_token出错")
return nil
}
// sprint: ustomfield_10005
// assignee
// let formData = "id=\(self.storyId)&atl_token=\(atl_token)&formToken=\(formToken)&summary=%E9%83%A8%E5%88%86%E9%A1%B5%E9%9D%A2%E5%8F%AA%E5%85%81%E8%AE%B8%E5%8F%AA%E5%BC%B9%E5%87%BA%E4%B8%80%E6%AC%A1&timetracking_originalestimate=&isCreateIssue=&hasWorkStarted=&issuetype=10001&assignee=wangyang&reporter=wangyang&customfield_10102=ceshi&description=&priority=3&issuelinks=issuelinks&issuelinks-linktype=blocks&customfield_10005=264&customfield_10103=&dnd-dropzone=&timetracking_remainingestimate=&worklog_timeLogged=&worklog_startDate=08%2FMar%2F19+4%3A40+PM&worklog_adjustEstimate=auto&isCreateIssue=false&isEditIssue=true&comment=&commentLevel="
let formData = "id=\(storyId)&atl_token=\(atl_token)&formToken=\(formToken)&assignee=\(assignee)&customfield_10005=\(RepeatedWork.sprint!.id)&isCreateIssue=false&isEditIssue=true&summary=\(summary)&issuetype=10001&reporter=wangyang"
let formData = "id=\(storyId)&atl_token=\(atl_token)&formToken=\(formToken)&assignee=\(assignee)&customfield_10005=\(RepeatedWork.sprint!.id)&isCreateIssue=false&isEditIssue=true&summary=\(summary)&issuetype=10001&reporter=wangyang&description=开始时间%2B开发人员%2B任务名称%2B预计开发时间"
return formData
}
/// 根据story创建每一个人的subtask
///
/// - Parameter page: page实例
static func createSubtask(page: Page) {
/// - Parameter page: page实例page: Page
func createSubtask(page: Page) {
Log.append("根据story创建subtask")
prepareForSubtask()
for assignee in page.developers {
let summary = "开始时间%2B\(assignee.name)%2B\(self.summary)%2B预计开发时间"
quickCreateSubtask(assignee: assignee.id, summary: summary)
}
if let foid = page.fo?.id {
quickCreateSubtask(assignee: foid, summary: "dev环境联调:xx号")
quickCreateSubtask(assignee: foid, summary: "Demo时间:xx号")
}
}
func quickCreateSubtask(assignee: String, summary: String) {
let url = URL(string: "http://jira.wanmeizhensuo.com/secure/QuickCreateIssue.jspa?decorator=none")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
let formString = "pid=\(pid)&issuetype=10003&parentIssueId=\(storyId)&atl_token=\(subtask_atl_token)&formToken=\(subtask_formToken)&summary=\(summary)&isCreateIssue=true&assignee=\(assignee)&reporter=wangyang&priority=3&issuelinks=issuelinks&issuelinks-linktype=blocks&isCreateIssue=true&isEditIssue=false&"
let formData = formString.data(using: .utf8)
request.httpBody = formData
request.sync { (data, response, error) in
if error != nil {
Log.append(error)
} else {
Log.append("创建subtask成功")
}
}
}
// 得到一些token,pid等信息
func prepareForSubtask() {
let url = URL(string: "http://jira.wanmeizhensuo.com/secure/QuickCreateIssue!default.jspa?parentIssueId=\(self.storyId)&decorator=none")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
var json: [String: Any]?
request.sync { (data, response, error) in
if data == nil {
Log.append(error)
return
}
json = (try? JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.allowFragments)) as? [String: Any]
}
if json == nil {
Log.append("secure/QuickEditIssue出错")
return
}
guard let formToken = json!["formToken"] as? String else {
Log.append("formToken出错")
return
}
self.subtask_formToken = formToken
guard let atl_token = json!["atl_token"] as? String else {
Log.append("atl_token出错")
return
}
self.subtask_atl_token = atl_token
guard let fields = json!["fields"] as? [[String: Any]] else {
Log.append("fields出错")
return
}
if fields.count == 0 {
Log.append("fields.count == 0 出错")
return
}
let firstField = fields[0]
let editHtml = firstField["editHtml"] as! String
guard let projectHtml = try? HTML(html: editHtml, encoding: .utf8) else {
Log.append("projectHtml出错")
return
}
guard let input = projectHtml.at_xpath("//input") else {
return
}
guard let pid = input["value"] else {
return
}
self.pid = pid
}
}
......@@ -6,4 +6,6 @@ http://jira.wanmeizhensuo.com/secure/QuickEditIssue.jspa?issueId=37334&decorator
curl -H 'Host: jira.wanmeizhensuo.com' -H 'Accept: */*' -H 'X-Requested-With: XMLHttpRequest' -H 'Accept-Language: zh-cn' -H 'X-AUSERNAME: wangyang' -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' -H 'Origin: http://jira.wanmeizhensuo.com' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.3 Safari/605.1.15' -H 'Referer: http://jira.wanmeizhensuo.com/browse/USER-13863' -H 'Cookie: JSESSIONID=733FD78BA713F0FC930D650717EE0400; atlassian.xsrf.token=BR38-RKGV-NWEL-Y2GE|1babc95b6be6c382931eb0214f830e3740b35fa9|lin; AJS.conglomerate.cookie="|hipchat.inapp.links.first.clicked.wangyang=false"; jira.editor.user.mode=wysiwyg' --data-binary "id=37334&atl_token=BR38-RKGV-NWEL-Y2GE%7C1babc95b6be6c382931eb0214f830e3740b35fa9%7Clin&formToken=7acd3d675fa47f74ced5e682691e245b1b750e66&summary=%E9%83%A8%E5%88%86%E9%A1%B5%E9%9D%A2%E5%8F%AA%E5%85%81%E8%AE%B8%E5%8F%AA%E5%BC%B9%E5%87%BA%E4%B8%80%E6%AC%A1&timetracking_originalestimate=&isCreateIssue=&hasWorkStarted=&issuetype=10001&assignee=wangyang&reporter=wangyang&customfield_10102=ceshi&description=&priority=3&issuelinks=issuelinks&issuelinks-linktype=blocks&customfield_10005=264&customfield_10103=&dnd-dropzone=&timetracking_remainingestimate=&worklog_timeLogged=&worklog_startDate=08%2FMar%2F19+4%3A40+PM&worklog_adjustEstimate=auto&isCreateIssue=false&isEditIssue=true&comment=&commentLevel=" --compressed 'http://jira.wanmeizhensuo.com/secure/QuickEditIssue.jspa?issueId=37334&decorator=none'
表单中:issuetype=10001 表示为story
表单中:
issuetype=10001 表示为story
ustomfield_10005 表示为迭代版本号
获取信息
curl -H 'Host: jira.wanmeizhensuo.com' -H 'X-Requested-With: XMLHttpRequest' -H 'Accept-Language: zh-cn' -H 'X-AUSERNAME: wangyang' -H 'Accept: */*' -H 'Origin: http://jira.wanmeizhensuo.com' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.3 Safari/605.1.15' -H 'Referer: http://jira.wanmeizhensuo.com/browse/USER-13894' -H 'Cookie: atlassian.xsrf.token=BR38-RKGV-NWEL-Y2GE|afc0a4b940c4b78a718075cd0500a44abf897d93|lin; JSESSIONID=8D362865E93DDDEB9A7D6E6E92D61604; AJS.conglomerate.cookie="|hipchat.inapp.links.first.clicked.wangyang=false"; jira.editor.user.mode=wysiwyg' --data-binary "" --compressed 'http://jira.wanmeizhensuo.com/secure/QuickCreateIssue!default.jspa?decorator=none&parentIssueId=37441'
创建问题
curl -H 'Host: jira.wanmeizhensuo.com' -H 'Accept: */*' -H 'X-Requested-With: XMLHttpRequest' -H 'Accept-Language: zh-cn' -H 'X-AUSERNAME: wangyang' -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' -H 'Origin: http://jira.wanmeizhensuo.com' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.3 Safari/605.1.15' -H 'Referer: http://jira.wanmeizhensuo.com/browse/USER-13894' -H 'Cookie: atlassian.xsrf.token=BR38-RKGV-NWEL-Y2GE|afc0a4b940c4b78a718075cd0500a44abf897d93|lin; JSESSIONID=8D362865E93DDDEB9A7D6E6E92D61604; AJS.conglomerate.cookie="|hipchat.inapp.links.first.clicked.wangyang=false"; jira.editor.user.mode=wysiwyg' --data-binary "pid=10108&issuetype=10003&parentIssueId=37441&atl_token=BR38-RKGV-NWEL-Y2GE%7Cafc0a4b940c4b78a718075cd0500a44abf897d93%7Clin&formToken=48fa29958e7feca99edb2a5ba8e83433708ca4df&summary=dd&timetracking_originalestimate=&isCreateIssue=true&hasWorkStarted=&assignee=wangyang&reporter=wangyang&customfield_10102=ceshi&description=&priority=3&issuelinks=issuelinks&issuelinks-linktype=blocks&customfield_10103=&dnd-dropzone=&timetracking_remainingestimate=&worklog_timeLogged=&worklog_startDate=11%2FMar%2F19+5%3A28+PM&worklog_adjustEstimate=auto&comment=&commentLevel=&isCreateIssue=true&isEditIssue=false&fieldsToRetain=project&fieldsToRetain=issuetype&fieldsToRetain=assignee&fieldsToRetain=fixVersions&fieldsToRetain=versions&fieldsToRetain=reporter&fieldsToRetain=customfield_10102&fieldsToRetain=components&fieldsToRetain=priority&fieldsToRetain=issuelinks&fieldsToRetain=labels&fieldsToRetain=customfield_10006&fieldsToRetain=customfield_10005&fieldsToRetain=customfield_10103" --compressed 'http://jira.wanmeizhensuo.com/secure/QuickCreateIssue.jspa?decorator=none'
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment