您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

  1. # frozen_string_literal: true
  2. require "oauth2"
  3. class Basecamp3
  4. attr_accessor :client, :api_url, :auth_info, :authorize_url, :request_count, :request_start, :ouath_token
  5. def initialize
  6. @client = OAuth2::Client.new(
  7. ENV["BASECAMP_CLIENT_ID"],
  8. ENV["BASECAMP_CLIENT_SECRET"],
  9. site: "https://launchpad.37signals.com",
  10. authorize_url: "/authorization/new",
  11. token_url: "/authorization/token"
  12. )
  13. @authorize_url = @client.auth_code.authorize_url(redirect_uri: ENV["REDIRECT_URL"], type: "web_server")
  14. if token
  15. token_record = token
  16. @ouath_token = OAuth2::AccessToken.from_hash(@client, token_record.oauth_hash)
  17. @ouath_token = @ouath_token.refresh if @ouath_token.expired?
  18. if token_record.auth_data.nil?
  19. token_record.auth_data = authorization
  20. token_record.save!
  21. end
  22. @auth_info = token_record.auth_data
  23. @api_url = @auth_info["accounts"][0]["href"]
  24. end
  25. end
  26. def token
  27. Token.find_by(client_id: ENV["BASECAMP_CLIENT_ID"])
  28. end
  29. def authenticated?
  30. return false unless @ouath_token
  31. @ouath_token = @ouath_token.refresh if @ouath_token.expired?
  32. true
  33. end
  34. def get_access_token(code)
  35. access_token_response = @client.auth_code.get_token(code, type: "web_server", redirect_uri: ENV["REDIRECT_URL"])
  36. @ouath_token = Token.find_or_initialize_by(client_id: ENV["BASECAMP_CLIENT_ID"])
  37. @ouath_token.update!(
  38. access_token: access_token_response.token,
  39. refresh_token: access_token_response.refresh_token,
  40. expires_in: access_token_response.expires_in,
  41. expires_at: DateTime.strptime(access_token_response.expires_at.to_s, "%s")
  42. )
  43. end
  44. def projects
  45. result = @ouath_token.get("#{@api_url}/projects.json")
  46. all_results(result)
  47. end
  48. def todo_lists
  49. todo_lists = []
  50. projects.each do |project|
  51. project_todo_set = project["dock"].find { |i| i["name"] == "todoset" }
  52. todolist_url = @ouath_token.get(project_todo_set["url"]).parsed["todolists_url"]
  53. todo_lists.concat(all_results(@ouath_token.get(todolist_url)))
  54. end
  55. todo_lists
  56. end
  57. def todo_items
  58. todo_items = []
  59. todo_lists.each do |list|
  60. todo_items.concat(all_results(@ouath_token.get(list["todos_url"])))
  61. end
  62. todo_items
  63. end
  64. private
  65. def authorization
  66. @ouath_token.get("/authorization.json").parsed
  67. end
  68. def all_results(result)
  69. if @request_start
  70. SuckerPunch.logger.info "Made #{@request_count} requests in #{(Time.now - @request_start).to_i} seconds"
  71. if (Time.now - @request_start).to_i > 10
  72. SuckerPunch.logger.info "Ten seconds with no problem? Cool. Resetting Counters"
  73. @request_start = Time.now
  74. @request_count = 1
  75. elsif @request_count >= 48 && ((Time.now - @request_start).to_i < 10)
  76. wait_time = (10 - (Time.now - @request_start).to_i).to_i + 2
  77. SuckerPunch.logger.info "Approaching rate limit! Waiting #{wait_time} seconds before carrying on."
  78. sleep wait_time
  79. @request_start = Time.now
  80. @request_count = 1
  81. end
  82. @request_count += 2
  83. end
  84. results = result.parsed || []
  85. if result.headers["x-total-count"].to_i > results.count
  86. until result.headers["link"].nil?
  87. url = result.headers["link"].gsub("<", "").split(">")[0]
  88. result = @ouath_token.get(url)
  89. results.concat(result.parsed)
  90. end
  91. end
  92. results
  93. end
  94. end