# 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