ecko-plugins-sponsor 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2beab402173ba1462a969906af825db63641f56bdb10916cc26f63c356ddad27
4
+ data.tar.gz: 0f6fa5357ed8c9465b83fcce4399a973f51732411486ff9667d57276636c6c8c
5
+ SHA512:
6
+ metadata.gz: 3e830986afae5fe73c0dca22e202ff76cd79cbc37cdcbead869eeb366b62e7f5b72bee8ab53062451bb9e0c0b1ac1e9a9c5ab596115a651161e66ae0a6005ed6
7
+ data.tar.gz: 9d9b961eff613e121fc5d664fbc1b96f91f54ee812ecd95e95bcc2a033edd5e84344ce690876b5f8f0e5366806dfdcecc80319d8c306baf53a2c2468faca2a68
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ecko
4
+ module Plugins
5
+ class DonationsController < 'ApplicationController'.constantize
6
+ layout 'public'
7
+
8
+ before_action :authenticate_user!
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ecko
4
+ module Plugins
5
+ module Sponsor
6
+ # This error can be raised when no gateways are configured
7
+ class NoGatewaysConfiguredError < StandardError; end
8
+
9
+ class Configurations
10
+ include Singleton
11
+ attr_accessor :schema
12
+
13
+ # Need to validate schema structure here
14
+ def setup(schema)
15
+ # Check any gateways where configured
16
+ raise NoGatewaysConfiguredError if schema[:gateways].blank?
17
+
18
+ # Validate configurations
19
+ schema[:gateways].each do |gateway|
20
+ Ecko::Plugins::Sponsor::SchemaValidator::GatewayValidator.validate(gateway)
21
+ Ecko::Plugins::Sponsor.add_gateway(gateway)
22
+ end
23
+
24
+ @schema = schema
25
+ end
26
+
27
+ def gateways
28
+ return { run: 'default', default: schema[:gateways].first } if schema[:gateways].length == 1
29
+
30
+ { run: 'choice', choices: schema[:gateways] }
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This class is used to perform post donation and add a donation to the account.
4
+ # This actually should be a service that app should run.
5
+ module Ecko
6
+ module Plugins
7
+ module Sponsor
8
+ class Donated
9
+ attr_accessor :intent, :account, :package
10
+
11
+ # Sets the intent of the donation and finds account and package with whom the
12
+ # intent is related to.
13
+ def initialize(intent)
14
+ @intent = intent
15
+ @account = ::Account.find(intent.payable_id)
16
+ @package = ::DonationPackage.find(intent.metadata['package_id'])
17
+ end
18
+
19
+ # Just the processor.
20
+ def process
21
+ create_donation && update_account_sponsorship && close_intent
22
+ end
23
+
24
+ private
25
+
26
+ # This is to help donations
27
+ def update_account_sponsorship
28
+ account.refresh_sponsorship
29
+ end
30
+
31
+ # Close the intent that was used for the donation
32
+ def close_intent
33
+ intent.update(status: 'closed')
34
+ end
35
+
36
+ # When the donation has been made, Create a donation for the account.
37
+ def create_donation
38
+ ::Donation.create(account: account, amount: package.amount)
39
+ end
40
+
41
+ class << self
42
+ def process(intent)
43
+ new(intent).process
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'configurations'
4
+ require_relative 'schema_validator'
5
+ require_relative 'process'
6
+
7
+ # This class is the engine of the sponsor plugin. IT doesnt do much but helps in
8
+ # redirecting process and configurations to different classes within the plugin.
9
+ # THis class is registered in the ecko plugins registry
10
+ module Ecko
11
+ module Plugins
12
+ module Sponsor
13
+ class Engine
14
+ class << self
15
+ # THis is the main engine configurer that the registry uses. THe schema is passed here
16
+ # and configured accordingly.
17
+ def configure(schema)
18
+ Ecko::Plugins::Sponsor::Configurations.instance.setup(schema)
19
+ end
20
+
21
+ # The gateways to be able to sponsor.
22
+ def gateways
23
+ Ecko::Plugins::Sponsor::Configurations.instance.gateways
24
+ end
25
+
26
+ # Processes the donation here.
27
+ def process(package_id, account)
28
+ Ecko::Plugins::Sponsor::Process.run(package_id, account)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require 'rails/generators'
5
+ rescue LoadError
6
+ end
7
+
8
+ if defined?(Rails::Generators::Base)
9
+ module Ecko
10
+ module Plugins
11
+ module Sponsor
12
+ class DonationPackageGenerator < Rails::Generators::Base
13
+ DATA_TYPES = %w(binary json jsonb).freeze
14
+
15
+ source_root File.expand_path(File.join(File.dirname(__FILE__), '../generators/templates'))
16
+ class_option(
17
+ :data_type,
18
+ type: :string,
19
+ default: 'binary',
20
+ desc: "Configure the data type for `data` and `meta data` fields in Postgres migration (options: #{DATA_TYPES.join('/')})"
21
+ )
22
+
23
+ def initialize(*args)
24
+ super
25
+
26
+ if DATA_TYPES.exclude?(options.fetch(:data_type))
27
+ raise Error, "Invalid value for --data-type option. Supported for options are: #{DATA_TYPES.join(", ")}."
28
+ end
29
+ end
30
+
31
+ # THis will help in generating new templates for donations service.
32
+ def create_migration
33
+ template 'create_donation_package_template.rb', "db/migrate/#{timestamp}_create_donation_packages.rb"
34
+ template 'donation_package.rb', 'app/models/donation_package.rb'
35
+ template 'donation.rb', 'app/models/donation.rb'
36
+ end
37
+
38
+ private
39
+
40
+ def data_type
41
+ options.fetch('data_type')
42
+ end
43
+
44
+ def rails_version
45
+ Rails::VERSION::STRING
46
+ end
47
+
48
+ def migration_version
49
+ return nil if Gem::Version.new(rails_version) < Gem::Version.new('5.0.0')
50
+ '[6.0]'
51
+ end
52
+
53
+ def timestamp
54
+ Time.now.strftime('%Y%m%d%H%M%S')
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+
@@ -0,0 +1,14 @@
1
+ class CreateDonationPackages < ActiveRecord::Migration[6.1]
2
+ def change
3
+ create_table :donation_packages do |t|
4
+ t.float :amount
5
+ t.integer :currency
6
+ t.string :title
7
+ t.text :description
8
+ t.integer :donation_reference, default: 0
9
+ t.boolean :visible, default: true
10
+
11
+ t.timestamps
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+ # == Schema Information
3
+ #
4
+ # Table name: donations
5
+ #
6
+ # id :bigint(8) not null, primary key
7
+ # account_id :bigint(8) not null
8
+ # amount :float not null
9
+ # created_at :datetime not null
10
+ # updated_at :datetime not null
11
+ #
12
+
13
+ class Donation < ApplicationRecord
14
+ belongs_to :account, inverse_of: :donations
15
+ end
@@ -0,0 +1,27 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: donation_packages
4
+ #
5
+ # id :bigint(8) not null, primary key
6
+ # amount :float
7
+ # currency :integer
8
+ # title :string
9
+ # description :text
10
+ # donation_reference :integer default("free_tier")
11
+ # visible :boolean default(TRUE)
12
+ # created_at :datetime not null
13
+ # updated_at :datetime not null
14
+ #
15
+ class DonationPackage < ApplicationRecord
16
+ scope :visible, -> { where(visible: true) }
17
+ enum donation_reference: {
18
+ free_tier: 0,
19
+ silver_tier: 100,
20
+ gold_tier: 1000,
21
+ platinum_tier: 2000
22
+ }
23
+ enum currency: {
24
+ usd: 0,
25
+ eur: 1
26
+ }
27
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ecko
4
+ module Plugins
5
+ module Sponsor
6
+ module Parser
7
+ class Stripe
8
+ attr_reader :package, :account
9
+
10
+ def initialize(package, account)
11
+ @package = package
12
+ @account = account
13
+ end
14
+
15
+ def build
16
+ {
17
+ submit_type: 'donate',
18
+ success_message: 'Thanks for being part of our community, Your donation was well received', # Need to add translation options,
19
+ callback: 'Ecko::Plugins::Sponsor::Donated',
20
+ package_id: package.id,
21
+ payable_type: account.class.name,
22
+ payable_id: account.id,
23
+ line_items: [
24
+ {
25
+ quantity: 1,
26
+ amount: package.amount,
27
+ name: "#{package.title} Donation",
28
+ description: 'Donation for the instance',
29
+ }
30
+ ]
31
+ }
32
+ end
33
+
34
+ class << self
35
+ def build(package, account)
36
+ new(package, account).build
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ecko/plugins/sponsor/parser/stripe'
4
+
5
+ # This class processes the gateway and parses the donation object. Currently only default option
6
+ # as a runner is provided but when adding multiple parsers in future, we will have a choice option when
7
+ # we add multiple gateways in the future.
8
+ module Ecko
9
+ module Plugins
10
+ module Sponsor
11
+ class Process
12
+ attr_accessor :package, :account
13
+
14
+ # Get the donation package and set it here. If it is not found, RecordNotFound error
15
+ # will be raised
16
+ def initialize(package_id, account)
17
+ # Find the package through which we can donate.
18
+ @package = ::DonationPackage.find(package_id)
19
+
20
+ # A sponsor should always be associated with an account
21
+ @account = account
22
+ end
23
+
24
+ # This will run the gateway process based on the object set during configuration
25
+ def run
26
+ send("run_#{gateways[:run]}")
27
+ end
28
+
29
+ private
30
+
31
+ # Currently we just have a stripe parser which will never run this process so it is an empty
32
+ # runner currently.
33
+ # TODO: Set this up when we have multiple parsers. It should not run gateway process but redirect to a choice of gateway
34
+ def run_choice; end
35
+
36
+ # When we have only a default processor, we just parse the gateway object
37
+ # and then run the checkout flow for it.
38
+ def run_default
39
+ value = Object.const_get("Ecko::Plugins::Sponsor::Parser::#{gateways[:default][:name]}").build(package, account)
40
+ gateways[:default][:checkout].execute(value)
41
+ end
42
+
43
+ # Gets all the gateways that was registered for this plugin.
44
+ def gateways
45
+ @gateways ||= Ecko::Plugins::Sponsor::Configurations.instance.gateways
46
+ end
47
+
48
+ class << self
49
+ def run(package_id, account)
50
+ new(package_id, account).run
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ecko
4
+ module Plugins
5
+ module Sponsor
6
+ class InvalidGatewayName < StandardError; end
7
+
8
+ class InvalidGatewayCheckout < StandardError; end
9
+
10
+ module SchemaValidator
11
+ class Base
12
+ attr_accessor :schema
13
+
14
+ def initialize(schema)
15
+ @schema = schema
16
+ end
17
+
18
+ class << self
19
+ def validate(schema)
20
+ new(schema).validate
21
+ end
22
+ end
23
+ end
24
+
25
+ class GatewayValidator < Base
26
+
27
+ # Validate all the gateway schema which helps in providing correct structure for the gateways
28
+ # that is used for donation
29
+ def validate
30
+ # Validate name
31
+ raise InvalidGatewayName if schema[:name].nil?
32
+
33
+ # validate checkout
34
+ raise InvalidGatewayCheckout if schema[:checkout].nil? || !schema[:checkout].is_a?(Class)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ecko
4
+ module Plugins
5
+ module Sponsor
6
+ VERSION = "0.1.0"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'sponsor/version'
4
+ require 'rails'
5
+ require 'ecko/plugins'
6
+ require_relative 'sponsor/engine'
7
+
8
+ module Ecko
9
+ module Plugins
10
+ module Sponsor
11
+ autoload(:Donated, 'ecko/plugins/sponsor/donated')
12
+
13
+ class Error < StandardError; end
14
+ @@gateways = []
15
+
16
+ class << self
17
+ # It will add all the gateways here to be able to redirect when someone tries to donate
18
+ # If none of the gateways are configured there are no ways to donate
19
+ # Therefore an error will be thrown
20
+ def add_gateway(checkout)
21
+ @@gateways << checkout
22
+ end
23
+
24
+ # We can get all the available gateways that we can use to donate.
25
+ def available_gateways
26
+ return { run: 'default', default: @@gateways.first } if @@gateways.length == 1
27
+
28
+ # The choice runner will help in setting up a UI for the users to
29
+ # choose which gateway do they prefer.
30
+ { run: 'choice', choices: @@gateways }
31
+ end
32
+
33
+ # THis will register the sponsor engine to the ecko plugin registry
34
+ def register(schema)
35
+ Ecko::Plugins.register(name: 'sponsor', schema: schema, engine: Ecko::Plugins::Sponsor::Engine)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ require 'ecko/plugins/sponsor/generator/donation_package_generator'
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ecko-plugins-sponsor
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Manish Sharma
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2022-01-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ecko-plugins
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.1.6
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.1.6
27
+ - !ruby/object:Gem::Dependency
28
+ name: rails
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 6.1.4
34
+ - - "<"
35
+ - !ruby/object:Gem::Version
36
+ version: 7.0.0
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 6.1.4
44
+ - - "<"
45
+ - !ruby/object:Gem::Version
46
+ version: 7.0.0
47
+ description: Adds mastodon functionality to donate to an instance and sponsorship
48
+ tags
49
+ email:
50
+ - arnoltherasing@gmail.com
51
+ executables: []
52
+ extensions: []
53
+ extra_rdoc_files: []
54
+ files:
55
+ - app/controllers/ecko/plugins/donations_controller.rb
56
+ - lib/ecko/plugins/sponsor.rb
57
+ - lib/ecko/plugins/sponsor/configurations.rb
58
+ - lib/ecko/plugins/sponsor/donated.rb
59
+ - lib/ecko/plugins/sponsor/engine.rb
60
+ - lib/ecko/plugins/sponsor/generator/donation_package_generator.rb
61
+ - lib/ecko/plugins/sponsor/generator/templates/create_donation_package_template.rb
62
+ - lib/ecko/plugins/sponsor/generator/templates/donation.rb
63
+ - lib/ecko/plugins/sponsor/generator/templates/donation_package.rb
64
+ - lib/ecko/plugins/sponsor/parser/stripe.rb
65
+ - lib/ecko/plugins/sponsor/process.rb
66
+ - lib/ecko/plugins/sponsor/schema_validator.rb
67
+ - lib/ecko/plugins/sponsor/version.rb
68
+ homepage: https://github.com/magicstone-dev/ecko-plugins/tree/main/ecko-plugins-sponsor
69
+ licenses:
70
+ - GPL-3.0+
71
+ metadata:
72
+ allowed_push_host: https://rubygems.org
73
+ homepage_uri: https://github.com/magicstone-dev/ecko-plugins/tree/main/ecko-plugins-sponsor
74
+ source_code_uri: https://github.com/magicstone-dev/ecko-plugins/tree/main/ecko-plugins-sponsor
75
+ changelog_uri: https://github.com/magicstone-dev/ecko-plugins/tree/main/ecko-plugins-sponsor
76
+ post_install_message:
77
+ rdoc_options: []
78
+ require_paths:
79
+ - lib
80
+ - app
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: 2.6.0
86
+ required_rubygems_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ requirements: []
92
+ rubygems_version: 3.1.6
93
+ signing_key:
94
+ specification_version: 4
95
+ summary: Adds sponsor functionality through donations
96
+ test_files: []