ecko-plugins-sponsor 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []