102 lines
3.4 KiB
Ruby
102 lines
3.4 KiB
Ruby
|
# frozen_string_literal: true
|
||
|
|
||
|
module Requests
|
||
|
class DiscordOauth
|
||
|
include HTTParty
|
||
|
base_uri "https://discord.com/api/oauth2"
|
||
|
|
||
|
Authorization = Struct.new(:access_token, :token_type, :expires_in, :refresh_token, :scope, :webhook) do
|
||
|
def get_authorization # rubocop:disable Naming/AccessorMethodName
|
||
|
r = DiscordOauth.get("/@me", {
|
||
|
headers: {
|
||
|
"Authorization" => "#{token_type} #{access_token}",
|
||
|
},
|
||
|
})
|
||
|
if r.code != 200
|
||
|
Rails.logger.error("Failed to get user info: #{r.code} #{r.body}")
|
||
|
return nil
|
||
|
end
|
||
|
JSON.parse(r.body)
|
||
|
end
|
||
|
|
||
|
def get_guilds # rubocop:disable Naming/AccessorMethodName
|
||
|
r = HTTParty.get("https://discord.com/api/users/@me/guilds", {
|
||
|
headers: {
|
||
|
"Authorization" => "#{token_type} #{access_token}",
|
||
|
},
|
||
|
})
|
||
|
if r.code != 200
|
||
|
Rails.logger.error("Failed to get user guilds: #{r.code} #{r.body}")
|
||
|
return nil
|
||
|
end
|
||
|
JSON.parse(r.body)
|
||
|
end
|
||
|
|
||
|
def user_id
|
||
|
get_authorization.try(:[], "user").try(:[], "id")
|
||
|
end
|
||
|
end
|
||
|
Webhook = Struct.new(:application_id, :name, :url, :channel_id, :token, :type, :avatar, :guild_id, :id)
|
||
|
Error = Struct.new(:error, :error_description)
|
||
|
|
||
|
attr_reader :client_id, :client_secret
|
||
|
|
||
|
def initialize(client_id:, client_secret:)
|
||
|
@client_id = client_id
|
||
|
@client_secret = client_secret
|
||
|
end
|
||
|
|
||
|
def authorize(redirect_uri:, code:)
|
||
|
data = self.class.post("/token", {
|
||
|
body: URI.encode_www_form({
|
||
|
grant_type: "authorization_code",
|
||
|
code: code,
|
||
|
redirect_uri: redirect_uri,
|
||
|
}),
|
||
|
basic_auth: {
|
||
|
username: client_id,
|
||
|
password: client_secret,
|
||
|
},
|
||
|
headers: {
|
||
|
"Content-Type" => "application/x-www-form-urlencoded",
|
||
|
},
|
||
|
})
|
||
|
unless data.success?
|
||
|
Rails.logger.info(client_id)
|
||
|
Rails.logger.error("Failed to authorize: #{data.code} #{data.body}")
|
||
|
end
|
||
|
return Error.new(data["error"], data["error_description"]) if data["error"]
|
||
|
|
||
|
hook = nil
|
||
|
hook = Webhook.new(data["webhook"]["application_id"], data["webhook"]["name"], data["webhook"]["url"], data["webhook"]["channel_id"], data["webhook"]["token"], data["webhook"]["type"], data["webhook"]["avatar"], data["webhook"]["guild_id"], data["webhook"]["id"]) if data["webhook"]
|
||
|
Authorization.new(data["access_token"], data["token_type"], data["expires_in"], data["refresh_token"], data["scope"], hook)
|
||
|
end
|
||
|
|
||
|
def client_grant(scopes:)
|
||
|
data = self.class.post("/token", {
|
||
|
body: URI.encode_www_form({
|
||
|
grant_type: "client_credentials",
|
||
|
scope: scopes.join(" "),
|
||
|
}),
|
||
|
basic_auth: {
|
||
|
username: client_id,
|
||
|
password: client_secret,
|
||
|
},
|
||
|
headers: {
|
||
|
"Content-Type" => "application/x-www-form-urlencoded",
|
||
|
},
|
||
|
})
|
||
|
return Error.new(data["error"], data["error_description"]) if data["error"]
|
||
|
|
||
|
Authorization.new(data["access_token"], data["token_type"], data["expires_in"], data["refresh_token"], data["scope"], nil)
|
||
|
end
|
||
|
|
||
|
def self.yiffy_client_credentials(scopes:)
|
||
|
new(
|
||
|
client_id: Websites.config.yiffyapi_discord_id,
|
||
|
client_secret: Websites.config.yiffyapi_discord_secret,
|
||
|
).client_grant(scopes: scopes)
|
||
|
end
|
||
|
end
|
||
|
end
|