Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save noppefoxwolf/6404f2d396c7aff7638703be18369447 to your computer and use it in GitHub Desktop.
Save noppefoxwolf/6404f2d396c7aff7638703be18369447 to your computer and use it in GitHub Desktop.
AppleMusicAPIからgolangのコード吐くやつ
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