Created
April 15, 2019 17:23
-
-
Save noppefoxwolf/6404f2d396c7aff7638703be18369447 to your computer and use it in GitHub Desktop.
AppleMusicAPIからgolangのコード吐くやつ
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import SwiftSoup | |
let base = "https://developer.apple.com" | |
func getURL(from url: String, viewBox: String) -> [String] { | |
let url = URL(string: url)! | |
let data = try! Data(contentsOf: url) | |
let doc: Document = try! SwiftSoup.parse(String(data: data, encoding: .utf8)!) | |
let taskTopics = try! doc.select("div").filter({ $0.hasClass("task-topic") }) | |
return taskTopics.filter({ | |
guard let a = (try! $0.getElementsByTag("a")).first() else { return false } | |
let href = try! a.attr("href") | |
// print(href) | |
guard let svg = (try! $0.getElementsByTag("svg")).first() else { return false } | |
let _viewBox = try! svg.attr("viewBox") | |
// print(viewBox) | |
return _viewBox == viewBox | |
}).compactMap({ | |
guard let a = (try! $0.getElementsByTag("a")).first() else { return nil } | |
return try! a.attr("href") | |
}) | |
} | |
struct Parameter { | |
let name: String | |
let type: String | |
let desc: String | |
let isRequired: Bool | |
var goType: String { | |
switch type { | |
case "[string]": return "[]string" | |
case "number": return "int" | |
case "integer": return "int" | |
default: return type | |
} | |
} | |
} | |
enum Method: String { | |
case get = "GET" | |
case post = "POST" | |
case put = "PUT" | |
case delete = "DELETE" | |
var name: String { | |
switch self { | |
case .get: return "Get" | |
case .post: return "Post" | |
case .put: return "Put" | |
case .delete: return "Delete" | |
} | |
} | |
} | |
extension String { | |
func capitalizingFirstLetter() -> String { | |
let str = self | |
let strLower = str.lowercased() | |
return String(strLower.prefix(1)).uppercased() + String(strLower.dropFirst()) | |
} | |
} | |
extension String { | |
// set `lower = false` in case you want "UpperCamel" output. | |
func camelized(lower: Bool = false) -> String { | |
guard self != "" else { return self } | |
let words = lowercased().split(separator: "_").map({ String($0) }) | |
let firstWord: String = words.first ?? "" | |
let camel: String = lower ? firstWord : String(firstWord.prefix(1).capitalized) + String(firstWord.suffix(from: index(after: startIndex))) | |
return words.dropFirst().reduce(into: camel, { camel, word in | |
camel.append(String(word.prefix(1).capitalized) + String(word.suffix(from: index(after: startIndex)))) | |
}) | |
} | |
} | |
struct API { | |
let service: String | |
let path: String | |
let method: Method | |
let description: String | |
let title: String | |
var methodTile: String { | |
return title.replacingOccurrences(of: "'", with: "").split(separator: " ").map({ String($0).capitalizingFirstLetter() }).reduce("", +) | |
} | |
let pathParams: [Parameter] | |
let queryParams: [Parameter] | |
let exampleJSON: String | |
let exampleURL: String | |
var paramsString: String { | |
var result = "" | |
for param in pathParams { | |
let omitEmpty = param.isRequired ? "" : ",omitempty" | |
result += "\(param.name.capitalizingFirstLetter()) \(param.goType) `url:\"-\(omitEmpty)\"` // \(param.desc)\n" | |
} | |
for param in queryParams { | |
let omitEmpty = param.isRequired ? "" : ",omitempty" | |
result += "\(param.name.capitalizingFirstLetter()) \(param.goType) `url:\"\(param.name)\(omitEmpty)\"` // \(param.desc)\n" | |
} | |
return result | |
} | |
var goCode: String { return """ | |
type \(methodTile)Params struct { | |
\(paramsString) | |
} | |
func (s *\(service.camelized())Service) \(methodTile)(params *\(methodTile)Params) (*models.VariableResponse, *http.Response, error) { | |
response := new(models.VariableResponse) | |
apiError := new(models.APIError) | |
resp, err := s.sling.New().\(method.name)("\(path)").QueryStruct(params).Receive(response, apiError) | |
return response, resp, relevantError(err, *apiError) | |
} | |
""".replacingOccurrences(of: "{storefront}", with: "\"+params.Storefront+\"") | |
.replacingOccurrences(of: "{id}", with: "\"+params.Id+\"") | |
.replacingOccurrences(of: "{relationship}", with: "\"+params.Relationship+\"") | |
} | |
var goTestCode: String { | |
return "" | |
} | |
} | |
func parseAPI(url: String, service: String) -> API { | |
let url = URL(string: url)! | |
let data = try! Data(contentsOf: url) | |
let doc: Document = try! SwiftSoup.parse(String(data: data, encoding: .utf8)!) | |
let title = try! doc.getElementsByClass("topic-heading").first()! | |
let description = try! doc.getElementsByClass("topic-description").first()! | |
let method = try! doc.getElementsByClass("endpointurl-method").first()! | |
let path = try! doc.getElementsByClass("endpointurl-path").first()! | |
var pathParams: [Parameter] = [] | |
if let pathParameters = try! doc.getElementById("path-parameters") { | |
for row in try! pathParameters.getElementsByClass("datatable-row") { | |
let name = try! row.getElementsByClass("parametertable-name").first()! | |
let type = try! row.getElementsByClass("parametertable-type").first()! | |
let desc = try! row.getElementsByClass("parametertable-description").first()! | |
let isNotRequired = try! row.getElementsByClass("parametertable-requirement").isEmpty() | |
let params = Parameter(name: try! name.text(), type: try! type.text(), desc: try! desc.text(), isRequired: !isNotRequired) | |
pathParams.append(params) | |
} | |
} | |
var queryParams: [Parameter] = [] | |
if let queryParameters = try! doc.getElementById("query-parameters") { | |
for row in try! queryParameters.getElementsByClass("datatable-row") { | |
let name = try! row.getElementsByClass("parametertable-name").first()! | |
let type = try! row.getElementsByClass("parametertable-type").first()! | |
let desc = try! row.getElementsByClass("parametertable-description").first()! | |
let isNotRequired = try! row.getElementsByClass("parametertable-requirement").isEmpty() | |
let params = Parameter(name: try! name.text(), type: try! type.text(), desc: try! desc.text(), isRequired: !isNotRequired) | |
queryParams.append(params) | |
} | |
} | |
let exampleURL = try! doc.getElementsByClass("collapsiblecode-line") | |
let exampleJson = try! doc.getElementsByClass("collapsiblecode-container") | |
return API(service: service, | |
path: try! path.text(), | |
method: Method(rawValue: try! method.text())!, | |
description: try! description.text(), | |
title: try! title.text(), | |
pathParams: pathParams, | |
queryParams: queryParams, | |
exampleJSON: try! exampleJson.text(), | |
exampleURL: try! exampleURL.text()) | |
} | |
let requestURLs = getURL(from: base + "/documentation/applemusicapi", viewBox: "0 0 15 16") | |
//debugPrint(requestURLs) | |
for reqURL in requestURLs { | |
// print(reqURL) | |
// continue | |
let service = URL(string: base + reqURL)!.lastPathComponent | |
let goServiceCode = """ | |
type \(service.camelized())Service struct { | |
sling *sling.Sling | |
} | |
func new\(service.camelized())Service(sling *sling.Sling) *\(service.camelized())Service { | |
return &\(service.camelized())Service{ | |
sling: sling.Path("/"), | |
} | |
} | |
""" | |
print(goServiceCode) | |
for apiURL in getURL(from: base + reqURL, viewBox: "0 0 20 22") { | |
let api = parseAPI(url: base + apiURL, service: service) | |
print(api.goCode) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment