Commit f6f736d7 authored by 汪洋's avatar 汪洋

可以关联story并正常指派给FO

parent 03393798
This diff is collapsed.
......@@ -7,7 +7,7 @@
<key>AutoJira.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
<integer>5</integer>
</dict>
</dict>
</dict>
......
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:AutoJira.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array/>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<Bucket
type = "0"
version = "2.0">
</Bucket>
This diff is collapsed.
......@@ -28,5 +28,27 @@
<string>Main</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>jira.wanmeizhensuo.com</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
<key>wiki.wanmeizhensuo.com</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
</dict>
</dict>
</dict>
</plist>
//
// Login.swift
// AutoJira
//
// Created by wangyang on 2019/3/5.
// Copyright © 2019 wangyang. All rights reserved.
//
import Foundation
struct Login {
// Login wangyang wind1988wind
static func loginWiki() {
let url = URL(string: "http://wiki.wanmeizhensuo.com/dologin.action")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
let form = "os_username=wangyang&os_password=wind1988wind&login=%E7%99%BB%E5%BD%95"
let formData = form.data(using: .utf8)
request.httpBody = formData
request.sync { (data, response, error) in
if error != nil {
Log.append(error)
} else {
Log.append("wiki登录成功")
}
}
}
static func loginJira() {
let url = URL(string: "http://jira.wanmeizhensuo.com/login.jsp")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
let form = "os_username=wangyang&os_password=wind1988wind&login=%E7%99%BB%E5%BD%95"
let formData = form.data(using: .utf8)
request.httpBody = formData
request.sync { (data, response, error) in
if error != nil {
Log.append(error)
} else {
Log.append("jira登录成功")
}
}
}
}
//
// Page.swift
// AutoJira
//
// Created by wangyang on 2019/2/26.
// Copyright © 2019 wangyang. All rights reserved.
//
import Cocoa
import Kanna
import ReactiveSwift
/*
可以使用html属性进一步来查看当前所代码的html代码。
*/
class Page: NSObject {
var pageId: String = ""
var title: String = ""
var story: Story!
var lastFetchTime: String = ""
var pageUrl: String = ""
let session = URLSession.shared
var html: HTMLDocument?
var fo: String = ""
var testers: [String] = []
var developers: [String] = []
convenience init(page: Kanna.XMLElement) {
self.init()
pageId = page["data-content-id"]!
title = page.text!
pageUrl = "http://wiki.wanmeizhensuo.com/pages/viewpage.action?pageId=" + pageId
html = loadHTML()
// 这个逻辑是模仿wiki页面中的javasript中的已有的逻辑
if let meta = html?.at_xpath("//meta[@name='confluence-request-time']") {
lastFetchTime = meta["content"]!
} else {
lastFetchTime = String(Int(Date().timeIntervalSince1970 * 1000))
}
// 核心是得到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)没有成功解析")
}
}
}
}
// 得到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!) 没有成功解析")
} else {
Log.append("\(foHtml)没有成功解析")
}
}
}
// 得到测试人员
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)没有成功解析")
}
}
}
}
}
func isValide() -> Bool {
if html == nil {
Log.append("\(pageUrl) 未正常解析")
return false
}
Log.append("创建Page成功: \(title)")
return true
}
// 下载需求页面,从中得到必要的信息
func loadHTML() -> HTMLDocument? {
let url = URL(string: pageUrl)!
var request = URLRequest(url: url)
request.httpMethod = "GET"
var html: HTMLDocument?
request.sync { (data, response, error) in
if data == nil {
html = nil
return
}
guard let htmlString = String(data: data!, encoding: .utf8) else {
html = nil
return
}
html = try? HTML(html: htmlString, encoding: .utf8)
}
return html
}
}
//
// ReapetWork.swift
// AutoJira
//
// Created by wangyang on 2019/2/28.
// Copyright © 2019 wangyang. All rights reserved.
//
import Foundation
import Kanna
import ReactiveCocoa
struct RepeatedWork {
static var sprint: Sprint?
// url是“开发与测试资源安排”中的迭代文件
static func fuckit(on sprintUrl: String) {
let url = URL(string: sprintUrl)!
var request = URLRequest(url: url)
request.httpMethod = "GET"
URLSession.shared.dataTask(with: request) { (data, response, error) in
DispatchQueue.main.async {
if data != nil {
doTheRepeatedWork(data!)
} else {
Log.append(error)
}
}
}.resume()
}
static func doTheRepeatedWork(_ data: Data) {
Log.append("开始重复工作")
guard let html = String(data: data, encoding: .utf8) else {
return
}
guard let doc = try? HTML(html: html, encoding: .utf8) else {
return
}
// 期望在这儿只得到主需求的列表
// 但是doc.xpath("//td[@data-content-id]")仍然得到了所有的
let obj = doc.xpath("//td[@data-content-id]")
if obj.count == 0 {
Log.append("没有需要列表\nhtml")
return
}
// 此处的每一个node就是一个需求,可以使用node.toHTML来查看其内容
for node in obj.makeIterator() {
let page = Page(page: node)
if !page.isValide() {
Log.append("page 信息有问题")
continue
}
if let story = Story.createStory(with: page.title) {
page.story = story
} else {
Log.append("story创建出错")
continue
}
page.story.connect(to: page.pageId, with: page.lastFetchTime)
page.story.editStoryInfo(assignee: page.fo)
// Story.createSubtask(page: page)
}
}
}
//
// Utils.swift
// AutoJira
//
// Created by wangyang on 2019/2/27.
// Copyright © 2019 wangyang. All rights reserved.
//
import Foundation
extension URLRequest {
static var jiraSession: String?
mutating func setJiraCookie() {
setValue("AJS.conglomerate.cookie=\"|hipchat.inapp.links.first.clicked.wangyang=false\"; atlassian.xsrf.token=BR38-RKGV-NWEL-Y2GE|59c084face9db734b606415629e67f572939e829|lin; JSESSIONID=A273C4AAFA2594506ABA814082718E0E; jira.editor.user.mode=wysiwyg", forHTTPHeaderField: "Cookie")
}
func sync(with completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) {
let semaphore = DispatchSemaphore(value: 0)
let dataTask = URLSession.shared.dataTask(with: self) { (data, response, error) in
completionHandler(data, response, error)
semaphore.signal()
}
dataTask.resume()
_ = semaphore.wait(timeout: .distantFuture)
}
}
//
// Wiki.swift
// AutoJira
//
// Created by wangyang on 2019/2/27.
// Copyright © 2019 wangyang. All rights reserved.
//
import Foundation
import Kanna
class Story: NSObject {
var storyKey: String = ""
var storyId: String = ""
var summary: String = ""
convenience init(storyKey: String, storyId: String) {
self.init()
self.storyId = storyId
self.storyKey = storyKey
}
/// 创建story
///
/// - Parameter page: Page实例
/// - Returns: storyKey
static func createStory(with title: String) -> Story? {
Log.append("创建story")
let url = URL(string: "http://wiki.wanmeizhensuo.com/rest/jira-integration/1.0/issues?applicationId=54ed5447-b029-3ef0-b638-681b4647313b")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let jsonDic = ["issues": [["fields":["project":["id":"10108"],"issuetype":["id":"10001"],"summary": title]]]]
request.httpBody = try? JSONSerialization.data(withJSONObject: jsonDic, options: [])
var story: Story?
request.sync { (data, response, error) in
if data == nil {
Log.append(error)
return
}
if let json = (try? JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.allowFragments)) as? [String: Any],
let issues = json["issues"] as? [Any],
let issueInfo = issues[0] as? [String: Any],
let issue = issueInfo["issue"] as? [String: Any],
let key = issue["key"] as? String,
let id = issue["id"] as? String {
story = Story(storyKey: key, storyId: id)
story?.summary = title
Log.append("创建story请求成功:\(story!.storyKey)")
} else {
Log.append("创建story请求失败:\n\(response.debugDescription)")
}
}
return story
}
/// 关联文档与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")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let bodyString = "{\"pageId\":\"\(pageId)\",\"selectedText\":\"项目背景\",\"index\":0,\"numMatches\":1,\"lastFetchTime\":\(pageLastFetchTime),\"xmlModification\":\"<ac:macro ac:name='jira'><ac:parameter ac:name='showSummary'>false</ac:parameter><ac:parameter ac:name='server'>JIRA</ac:parameter><ac:parameter ac:name='serverId'>54ed5447-b029-3ef0-b638-681b4647313b</ac:parameter><ac:parameter ac:name='key'>\(storyKey)</ac:parameter></ac:macro>\"}"
let data = bodyString.data(using: .utf8)
request.httpBody = data
request.sync { (data, response, error) in
if error != nil {
Log.append(error)
return
}
if let json = (try? JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.allowFragments)) as? Bool {
if json {
Log.append("关联story与wiki成功")
} else {
Log.append("关联story与wiki失败,很有可能是文档中没有\"项目背景\"四个字。response:\n \(response.debugDescription)")
}
return
} else {
Log.append("关联story与wiki失败,json没有正常解析。response:\n \(response.debugDescription)")
}
}
}
/// 修改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"
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
guard let formString = getEditIssueFormdata(assignee: assignee) else {
Log.append("editStoryInfo 失败")
return
}
let formData = formString.data(using: .utf8)
request.httpBody = formData
request.sync { (data, response, error) in
if error != nil {
Log.append(error)
} else {
Log.append("修改issue成功")
}
}
}
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)
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 nil
}
guard let formToken = json!["formToken"] else {
Log.append("formToken出错")
return nil
}
guard let atl_token = json!["atl_token"] 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"
return formData
}
/// 根据story创建每一个人的subtask
///
/// - Parameter page: page实例
static func createSubtask(page: Page) {
Log.append("根据story创建subtask")
}
}
......@@ -7,21 +7,131 @@
//
import Cocoa
import Kanna
class ViewController: NSViewController {
enum SprintState: String {
case future = "FUTURE"
case active = "ACTIVE"
case none = ""
}
struct Sprint {
let name: String
let id: Int
let stateKey: SprintState
init(dic: [String: Any]) {
if let name = dic["name"] as? String,
let id = dic["id"] as? Int,
let stateKey = dic["stateKey"] as? String,
let s = SprintState(rawValue: stateKey) {
self.name = name
self.id = id
self.stateKey = s
} else {
name = ""
id = 0
stateKey = .none
}
}
}
class ViewController: NSViewController {
@IBOutlet var logTextView: NSTextView!
@IBOutlet weak var urlTextField: NSTextField!
@IBOutlet weak var versionPopup: NSPopUpButton!
var gengmeiSprints: [Sprint] = []
var likeSprints: [Sprint] = []
var allSprints: [Sprint] = []
override func viewDidLoad() {
super.viewDidLoad()
Login.loginWiki()
Login.loginJira()
fetchSprintList()
for sprint in allSprints {
versionPopup.addItem(withTitle: sprint.name)
print("\(sprint.name) \(sprint.id)")
}
}
@IBAction func OKAction(_ sender: Any) {
if RepeatedWork.sprint == nil {
Log.append("先选择版本号")
return
}
if urlTextField.stringValue.count == 0 ||
urlTextField.stringValue.count == 0 {
Log.append("需求列表地址没有填写")
return
}
RepeatedWork.fuckit(on: urlTextField.stringValue)
}
// Do any additional setup after loading the view.
@IBAction func versionSelectionAction(_ sender: NSPopUpButton) {
if sender.indexOfSelectedItem > 0 {
RepeatedWork.sprint = allSprints[sender.indexOfSelectedItem - 1]
} else {
RepeatedWork.sprint = nil
}
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
// 参考"获取迭代列表.md"
func fetchSprintList() {
let url = URL(string: "http://jira.wanmeizhensuo.com/rest/greenhopper/1.0/sprint/picker?query=&_=1552128647090")!
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.sync { [weak self] (data, response, error) in
if data == nil {
Log.append(error)
return
}
if self == nil {
Log.append("fetchSprintList self 为空")
return
}
if let json = (try? JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.allowFragments)) as? [String: Any] {
guard let sprints = json["suggestions"] as? [[String: Any]] else {
Log.append("json中没有suggestions")
return
}
for sprintDic in sprints {
if let boardName = sprintDic["boardName"] as? String {
if boardName == "Alpha" {
self?.allSprints.append(Sprint(dic: sprintDic))
} else if boardName == "USER board" {
self?.allSprints.append(Sprint(dic: sprintDic))
}
}
}
} else {
Log.append("获取迭代列表失败:\n\(response.debugDescription)")
}
}
}
@IBAction func switchProject(_ sender: NSSegmentedControl) {
}
}
class Log: NSObject {
static func append(_ logText: String) {
DispatchQueue.main.async {
if let controller = NSApplication.shared.keyWindow?.contentViewController as? ViewController {
let textStorage = controller.logTextView.textStorage!
textStorage.append(NSAttributedString(string: "\n"))
textStorage.append(NSAttributedString(string: logText))
}
}
}
static func append(_ error: Error?) {
DispatchQueue.main.async {
if let err = error as NSError? {
append(err.localizedDescription)
}
}
}
}
## 功能
给定一个迭代的需求列表,该列表下的所有需求自动创建story,自动创建基本的subtask,包含联调时间,Demo时间的格式预置
开发人员修改subtask标题,以满足我们拆分任务的要求
开发人员根据story创建更多的subtask
## 代码阅读帮助
- 因为需要解析HTML,所以使用了Kanna库
- Kanna中使用了XPath知识:http://www.w3school.com.cn/xpath/xpath_syntax.asp
- 项目中多处使用同步请求网络,简化开发流程
XPath备忘
```
// 得到第一个 class 为 detailssummary
// 不过这个现在还没有什么实质用途
// guard let wikis = doc.at_xpath("//div[@data-macro-name='detailssummary']") else {
// return
// }
// print("\(String(describing: wiki.toHTML!))")
```
http://jira.wanmeizhensuo.com/secure/QuickEditIssue.jspa?issueId=37334&decorator=none
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
需求与story关联
```
curl -H 'Host: wiki.wanmeizhensuo.com' -H 'Accept: *' -H 'X-Requested-With: XMLHttpRequest' -H 'Accept-Language: zh-cn' -H 'Content-Type: application/json' -H 'Origin: http://wiki.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://wiki.wanmeizhensuo.com/pages/viewpage.action?pageId=11610551' -H 'Cookie: mywork.tab.tasks=false; JSESSIONID=22CBCCA5B598223EBF214B9FA4D89058; confluence.browse.space.cookie=space-templates; seraph.confluence=15991140%3Aa9bbc2621c1c53c9a71939b8643f2985f1ca9268; confluence.list.pages.cookie=list-content-tree' --data-binary "{\"pageId\":\"11610551\",\"selectedText\":\"需求正文\",\"index\":0,\"numMatches\":1,\"lastFetchTime\":\"1551154495201\",\"xmlModification\":\"<ac:macro ac:name='jira'><ac:parameter ac:name='showSummary'>false</ac:parameter><ac:parameter ac:name='server'>JIRA</ac:parameter><ac:parameter ac:name='serverId'>54ed5447-b029-3ef0-b638-681b4647313b</ac:parameter><ac:parameter ac:name='key'>USER-13798</ac:parameter>\\"</ac:macro>\"}" --compressed 'http://wiki.wanmeizhensuo.com/rest/highlighting/1.0/insert-storage-fragment'
Response
true
```
创建story
```
curl -H 'Host: wiki.wanmeizhensuo.com' -H 'Accept: *' -H 'X-Requested-With: XMLHttpRequest' -H 'Accept-Language: zh-cn' -H 'Content-Type: application/json' -H 'Origin: http://wiki.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://wiki.wanmeizhensuo.com/pages/viewpage.action?pageId=11610551' -H 'Cookie: mywork.tab.tasks=false; JSESSIONID=22CBCCA5B598223EBF214B9FA4D89058; confluence.browse.space.cookie=space-templates; seraph.confluence=15991140%3Aa9bbc2621c1c53c9a71939b8643f2985f1ca9268; confluence.list.pages.cookie=list-content-tree' --data-binary '{"issues":[{"fields":{"project":{"id":"10108"},"issuetype":{"id":"10001"},"summary":"部分页面只允许只弹出一次"}}]}' --compressed 'http://wiki.wanmeizhensuo.com/rest/jira-integration/1.0/issues?applicationId=54ed5447-b029-3ef0-b638-681b4647313b'
Response
{"issues":[{"issue":{"id":"37240","key":"USER-13798","self":"http:\/\/jira.wanmeizhensuo.com\/rest\/api\/2\/issue\/37240"},"elementNumber":0}]}
```
curl -H 'Host: wiki.wanmeizhensuo.com' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Language: zh-cn' -H 'Origin: http://wiki.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 'Upgrade-Insecure-Requests: 1' -H 'Referer: http://wiki.wanmeizhensuo.com/login.action?os_destination=%2Fpages%2Fviewpage.action%3FpageId%3D18581629&permissionViolation=true' -H 'Cookie: JSESSIONID=DBCF729710CA530DC9D17C37F0B075C3; mywork.tab.tasks=false; confluence.browse.space.cookie=space-templates; confluence.list.pages.cookie=list-content-tree' --data "os_username=wangyang&os_password=wind1988wind&login=%E7%99%BB%E5%BD%95&os_destination=%2Fpages%2Fviewpage.action%3FpageId%3D18581629" --compressed 'http://wiki.wanmeizhensuo.com/dologin.action'
提交的表单中
- os_destination用来表示下一步302会中转到哪个页面,这里我们不需要用到
http://jira.wanmeizhensuo.com/secure/QuickEditIssue!default.jspa?issueId=37334&decorator=none
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-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 "" --compressed 'http://jira.wanmeizhensuo.com/secure/QuickEditIssue!default.jspa?issueId=37334&decorator=none'
curl -H 'Host: jira.wanmeizhensuo.com' -H 'Accept: application/json, text/javascript, */*; q=0.01' -H 'X-Requested-With: XMLHttpRequest' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36' -H 'X-AUSERNAME: wangyang' -H 'Referer: http://jira.wanmeizhensuo.com/browse/USER-13863' -H 'Accept-Language: zh-CN,zh;q=0.9' -H 'Cookie: JSESSIONID=1F1A421A6C9A2D9C8E87F2783A5146F0; atlassian.xsrf.token=BR38-RKGV-NWEL-Y2GE|523d60740034d131898219b40536bd0fc9267c41|lin; AJS.conglomerate.cookie="|hipchat.inapp.links.first.clicked.wangyang=false"; jira.editor.user.mode=wysiwyg' --compressed 'http://jira.wanmeizhensuo.com/rest/greenhopper/1.0/sprint/picker?query=&_=1552128647090'
{
"suggestions": [{
"name": "alpha1.0.5",
"id": 258,
"stateKey": "ACTIVE",
"boardName": "Alpha",
"date": "2018-12-17T11:16:0Z"
}, {
"name": "DODING",
"id": 245,
"stateKey": "FUTURE",
"boardName": "Copy of DATA board",
"date": ""
}, {
"name": "alpha1.0.10",
"id": 261,
"stateKey": "FUTURE",
"boardName": "Alpha",
"date": ""
}, {
"name": "TDB",
"id": 246,
"stateKey": "FUTURE",
"boardName": "Copy of DATA board",
"date": ""
}, {
"name": "alpha1.15",
"id": 262,
"stateKey": "FUTURE",
"boardName": "Alpha",
"date": ""
}, {
"name": "Sprint-7755",
"id": 264,
"stateKey": "ACTIVE",
"boardName": "USER board",
"date": "2019-02-13T11:58:32Z"
}, {
"name": "Sprint-7760",
"id": 265,
"stateKey": "FUTURE",
"boardName": "USER board",
"date": ""
}, {
"name": "alpha1.4.0",
"id": 266,
"stateKey": "FUTURE",
"boardName": "Alpha",
"date": ""
}],
"allMatches": []
}
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'
target 'AutoJira' do
# Comment the next line if you're not using Swift and don't want to use dynamic frameworks
use_frameworks!
# Pods for AutoJira
pod 'Kanna', '~> 4.0.0'
pod 'ReactiveCocoa'
pod 'SwiftEventBus'
end
PODS:
- Kanna (4.0.2)
- ReactiveCocoa (8.0.2):
- ReactiveSwift (~> 4.0)
- ReactiveSwift (4.0.0):
- Result (~> 4.0)
- Result (4.0.0)
DEPENDENCIES:
- Kanna (~> 4.0.0)
- ReactiveCocoa
SPEC REPOS:
https://github.com/cocoapods/specs.git:
- Kanna
- ReactiveCocoa
- ReactiveSwift
- Result
SPEC CHECKSUMS:
Kanna: c60b61d72554bf04ed1ee074f9b379855cab4892
ReactiveCocoa: fbd26e9ba60e98417ee47433e59465a98ed9da0f
ReactiveSwift: a2bb9ace428a109e9c0209615645d9d286c8c433
Result: 7645bb3f50c2ce726dd0ff2fa7b6f42bbe6c3713
PODFILE CHECKSUM: 2fe4792843710f18988a19b2f628d7d3ded0e15a
COCOAPODS: 1.6.0.beta.2
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