instagram_connect 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 +7 -0
- data/.github/workflows/ci.yml +41 -0
- data/.rspec +2 -0
- data/CHANGELOG.md +30 -0
- data/Gemfile +16 -0
- data/LICENSE.txt +21 -0
- data/MIT-LICENSE +20 -0
- data/README.md +145 -0
- data/Rakefile +7 -0
- data/app/controllers/instagram_connect/application_controller.rb +30 -0
- data/app/controllers/instagram_connect/comments_controller.rb +59 -0
- data/app/controllers/instagram_connect/conversations_controller.rb +17 -0
- data/app/controllers/instagram_connect/messages_controller.rb +19 -0
- data/app/controllers/instagram_connect/oauth_controller.rb +43 -0
- data/app/controllers/instagram_connect/posts_controller.rb +40 -0
- data/app/controllers/instagram_connect/webhooks_controller.rb +54 -0
- data/app/jobs/instagram_connect/application_job.rb +4 -0
- data/app/jobs/instagram_connect/ingest_job.rb +11 -0
- data/app/jobs/instagram_connect/refresh_tokens_job.rb +22 -0
- data/app/jobs/instagram_connect/send_message_job.rb +44 -0
- data/app/models/instagram_connect/account.rb +36 -0
- data/app/models/instagram_connect/application_record.rb +5 -0
- data/app/models/instagram_connect/comment.rb +26 -0
- data/app/models/instagram_connect/conversation.rb +43 -0
- data/app/models/instagram_connect/inbound_message.rb +15 -0
- data/app/models/instagram_connect/message.rb +37 -0
- data/app/views/instagram_connect/comments/_comment.html.erb +19 -0
- data/app/views/instagram_connect/comments/index.html.erb +11 -0
- data/app/views/instagram_connect/conversations/_composer.html.erb +15 -0
- data/app/views/instagram_connect/conversations/_conversation.html.erb +11 -0
- data/app/views/instagram_connect/conversations/_message.html.erb +6 -0
- data/app/views/instagram_connect/conversations/index.html.erb +11 -0
- data/app/views/instagram_connect/conversations/show.html.erb +12 -0
- data/app/views/instagram_connect/posts/index.html.erb +23 -0
- data/app/views/instagram_connect/posts/new.html.erb +17 -0
- data/app/views/layouts/instagram_connect/application.html.erb +19 -0
- data/bin/instagram_connect +6 -0
- data/config/routes.rb +28 -0
- data/docs/app_review_guide.md +57 -0
- data/docs/auth_paths.md +42 -0
- data/docs/roadmap.md +27 -0
- data/lib/generators/instagram_connect/controllers_generator.rb +16 -0
- data/lib/generators/instagram_connect/install/install_generator.rb +40 -0
- data/lib/generators/instagram_connect/install/templates/create_instagram_connect_accounts.rb.tt +16 -0
- data/lib/generators/instagram_connect/install/templates/create_instagram_connect_comments.rb.tt +17 -0
- data/lib/generators/instagram_connect/install/templates/create_instagram_connect_conversations.rb.tt +16 -0
- data/lib/generators/instagram_connect/install/templates/create_instagram_connect_inbound_messages.rb.tt +11 -0
- data/lib/generators/instagram_connect/install/templates/create_instagram_connect_messages.rb.tt +25 -0
- data/lib/generators/instagram_connect/install/templates/instagram_connect.rb.tt +35 -0
- data/lib/generators/instagram_connect/views_generator.rb +16 -0
- data/lib/instagram_connect/auth/facebook_login.rb +68 -0
- data/lib/instagram_connect/auth/instagram_login.rb +73 -0
- data/lib/instagram_connect/auth/strategy.rb +70 -0
- data/lib/instagram_connect/auth.rb +17 -0
- data/lib/instagram_connect/cli.rb +18 -0
- data/lib/instagram_connect/client.rb +160 -0
- data/lib/instagram_connect/configuration.rb +66 -0
- data/lib/instagram_connect/connect.rb +45 -0
- data/lib/instagram_connect/doctor.rb +22 -0
- data/lib/instagram_connect/engine.rb +28 -0
- data/lib/instagram_connect/errors.rb +25 -0
- data/lib/instagram_connect/ingest.rb +112 -0
- data/lib/instagram_connect/messaging_window.rb +42 -0
- data/lib/instagram_connect/railtie.rb +19 -0
- data/lib/instagram_connect/result.rb +34 -0
- data/lib/instagram_connect/signature_verifier.rb +23 -0
- data/lib/instagram_connect/version.rb +3 -0
- data/lib/instagram_connect.rb +53 -0
- metadata +160 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
module InstagramConnect
|
|
2
|
+
# Parses a verified Meta webhook payload and persists it into the engine's
|
|
3
|
+
# chat models, deduping on Meta's message id. After persistence it fires the
|
|
4
|
+
# configured host handlers (on_message / on_comment / on_postback) so the host
|
|
5
|
+
# can layer extras (notifications, AI replies) on top.
|
|
6
|
+
#
|
|
7
|
+
# Returns a summary hash of what was processed.
|
|
8
|
+
class Ingest
|
|
9
|
+
def self.call(payload:, config: InstagramConnect.configuration)
|
|
10
|
+
new(config).call(payload)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def initialize(config)
|
|
14
|
+
@config = config
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def call(payload)
|
|
18
|
+
summary = { messages: 0, comments: 0, postbacks: 0, skipped: 0 }
|
|
19
|
+
Array(payload && payload["entry"]).each do |entry|
|
|
20
|
+
account = account_for(entry)
|
|
21
|
+
if account.nil?
|
|
22
|
+
summary[:skipped] += 1
|
|
23
|
+
next
|
|
24
|
+
end
|
|
25
|
+
Array(entry["messaging"]).each { |event| ingest_messaging(account, event, summary) }
|
|
26
|
+
Array(entry["changes"]).each { |change| ingest_change(account, change, summary) }
|
|
27
|
+
end
|
|
28
|
+
summary
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
attr_reader :config
|
|
34
|
+
|
|
35
|
+
def account_for(entry)
|
|
36
|
+
id = entry["id"].to_s
|
|
37
|
+
Account.find_by(ig_user_id: id) || Account.find_by(page_id: id)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def ingest_messaging(account, event, summary)
|
|
41
|
+
if event["message"]
|
|
42
|
+
ingest_message(account, event, summary)
|
|
43
|
+
elsif event["postback"]
|
|
44
|
+
invoke(config.on_postback, build_postback(account, event))
|
|
45
|
+
summary[:postbacks] += 1
|
|
46
|
+
else
|
|
47
|
+
summary[:skipped] += 1
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def ingest_message(account, event, summary)
|
|
52
|
+
msg = event["message"]
|
|
53
|
+
mid = msg["mid"].to_s
|
|
54
|
+
if mid.empty? || !InboundMessage.claim(ig_message_id: mid, account_id: account.id)
|
|
55
|
+
summary[:skipped] += 1
|
|
56
|
+
return
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
echo = msg["is_echo"] ? true : false
|
|
60
|
+
igsid = (echo ? event.dig("recipient", "id") : event.dig("sender", "id")).to_s
|
|
61
|
+
conversation = Conversation.locate(account: account, igsid: igsid)
|
|
62
|
+
message = Message.create!(
|
|
63
|
+
conversation: conversation,
|
|
64
|
+
direction: echo ? "outbound" : "inbound",
|
|
65
|
+
status: echo ? "sent" : "received",
|
|
66
|
+
source: echo ? "operator_app" : "inbound",
|
|
67
|
+
kind: "dm",
|
|
68
|
+
body: msg["text"],
|
|
69
|
+
ig_message_id: mid,
|
|
70
|
+
media_status: media?(msg) ? "pending" : "none"
|
|
71
|
+
)
|
|
72
|
+
conversation.register_message(message)
|
|
73
|
+
invoke(config.on_message, message) unless echo
|
|
74
|
+
summary[:messages] += 1
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def ingest_change(account, change, summary)
|
|
78
|
+
unless change["field"] == "comments"
|
|
79
|
+
summary[:skipped] += 1
|
|
80
|
+
return
|
|
81
|
+
end
|
|
82
|
+
value = change["value"] || {}
|
|
83
|
+
comment = Comment.record(
|
|
84
|
+
account: account,
|
|
85
|
+
comment_id: value["id"].to_s,
|
|
86
|
+
media_id: value.dig("media", "id"),
|
|
87
|
+
text: value["text"],
|
|
88
|
+
from_username: value.dig("from", "username"),
|
|
89
|
+
parent_id: value["parent_id"]
|
|
90
|
+
)
|
|
91
|
+
invoke(config.on_comment, comment)
|
|
92
|
+
summary[:comments] += 1
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def media?(msg)
|
|
96
|
+
Array(msg["attachments"]).any?
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def build_postback(account, event)
|
|
100
|
+
{
|
|
101
|
+
account_id: account.id,
|
|
102
|
+
sender_id: event.dig("sender", "id"),
|
|
103
|
+
payload: event.dig("postback", "payload"),
|
|
104
|
+
title: event.dig("postback", "title")
|
|
105
|
+
}
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def invoke(handler, arg)
|
|
109
|
+
handler.call(arg) if handler.respond_to?(:call)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
module InstagramConnect
|
|
2
|
+
# Encodes Meta's outbound messaging window. After a user's last inbound
|
|
3
|
+
# message a business may send standard replies for 24h; the HUMAN_AGENT tag
|
|
4
|
+
# extends that to 7 days (human replies only). Beyond that, nothing may be
|
|
5
|
+
# sent until the user messages again.
|
|
6
|
+
class MessagingWindow
|
|
7
|
+
STANDARD_SECONDS = 24 * 60 * 60
|
|
8
|
+
HUMAN_AGENT_SECONDS = 7 * 24 * 60 * 60
|
|
9
|
+
|
|
10
|
+
def initialize(last_inbound_at:, now: Time.now)
|
|
11
|
+
@last_inbound_at = last_inbound_at
|
|
12
|
+
@now = now
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def state
|
|
16
|
+
return :closed if @last_inbound_at.nil?
|
|
17
|
+
|
|
18
|
+
elapsed = @now - @last_inbound_at
|
|
19
|
+
return :standard if elapsed <= STANDARD_SECONDS
|
|
20
|
+
return :human_agent if elapsed <= HUMAN_AGENT_SECONDS
|
|
21
|
+
|
|
22
|
+
:closed
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def open?
|
|
26
|
+
state != :closed
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def standard?
|
|
30
|
+
state == :standard
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# The message tag to send with, or :blocked when no send is permitted.
|
|
34
|
+
def send_tag
|
|
35
|
+
case state
|
|
36
|
+
when :standard then nil
|
|
37
|
+
when :human_agent then "HUMAN_AGENT"
|
|
38
|
+
else :blocked
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require "rails/railtie"
|
|
2
|
+
|
|
3
|
+
module InstagramConnect
|
|
4
|
+
# Loaded when Rails is present but the full Engine is not (e.g. a bare Rails
|
|
5
|
+
# app that only wants the client, not the mounted UI). Mirrors the engine's
|
|
6
|
+
# configure initializer.
|
|
7
|
+
class Railtie < ::Rails::Railtie
|
|
8
|
+
config.instagram_connect = {}
|
|
9
|
+
|
|
10
|
+
initializer "instagram_connect.configure" do |app|
|
|
11
|
+
InstagramConnect.configure do |config|
|
|
12
|
+
app.config.instagram_connect.each do |key, value|
|
|
13
|
+
setter = "#{key}="
|
|
14
|
+
config.public_send(setter, value) if config.respond_to?(setter)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module InstagramConnect
|
|
2
|
+
# Value object returned by every Client call. Client methods never raise for
|
|
3
|
+
# API-level failures — callers branch on +success?+ and read +error_code+ /
|
|
4
|
+
# +error_message+. Transport/programming errors still raise.
|
|
5
|
+
class Result
|
|
6
|
+
attr_reader :success, :id, :error_code, :error_message, :retry_after, :data
|
|
7
|
+
|
|
8
|
+
def initialize(success:, id: nil, error_code: nil, error_message: nil, retry_after: nil, data: {})
|
|
9
|
+
@success = success
|
|
10
|
+
@id = id
|
|
11
|
+
@error_code = error_code
|
|
12
|
+
@error_message = error_message
|
|
13
|
+
@retry_after = retry_after
|
|
14
|
+
@data = data || {}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def success?
|
|
18
|
+
success
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def failure?
|
|
22
|
+
!success?
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Convenience builders so call sites read cleanly.
|
|
26
|
+
def self.ok(id: nil, data: {})
|
|
27
|
+
new(success: true, id: id, data: data)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.error(message, error_code: nil, retry_after: nil, data: {})
|
|
31
|
+
new(success: false, error_message: message, error_code: error_code, retry_after: retry_after, data: data)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require "openssl"
|
|
2
|
+
|
|
3
|
+
module InstagramConnect
|
|
4
|
+
# Verifies Meta's `X-Hub-Signature-256` header: HMAC-SHA256 of the raw request
|
|
5
|
+
# body keyed by the app secret, compared in constant time. This is how the
|
|
6
|
+
# webhook authenticates that a POST really came from Meta.
|
|
7
|
+
module SignatureVerifier
|
|
8
|
+
module_function
|
|
9
|
+
|
|
10
|
+
def valid?(raw_body:, signature:, app_secret: InstagramConnect.configuration.app_secret)
|
|
11
|
+
return false if signature.to_s.empty? || app_secret.to_s.empty?
|
|
12
|
+
|
|
13
|
+
expected = "sha256=#{OpenSSL::HMAC.hexdigest('SHA256', app_secret.to_s, raw_body.to_s)}"
|
|
14
|
+
secure_compare(signature.to_s, expected)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def secure_compare(given, expected)
|
|
18
|
+
return false unless given.bytesize == expected.bytesize
|
|
19
|
+
|
|
20
|
+
OpenSSL.fixed_length_secure_compare(given, expected)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
require "logger"
|
|
2
|
+
require_relative "instagram_connect/version"
|
|
3
|
+
require_relative "instagram_connect/errors"
|
|
4
|
+
require_relative "instagram_connect/result"
|
|
5
|
+
require_relative "instagram_connect/configuration"
|
|
6
|
+
require_relative "instagram_connect/auth/strategy"
|
|
7
|
+
require_relative "instagram_connect/auth/instagram_login"
|
|
8
|
+
require_relative "instagram_connect/auth/facebook_login"
|
|
9
|
+
require_relative "instagram_connect/auth"
|
|
10
|
+
require_relative "instagram_connect/client"
|
|
11
|
+
require_relative "instagram_connect/connect"
|
|
12
|
+
require_relative "instagram_connect/signature_verifier"
|
|
13
|
+
require_relative "instagram_connect/messaging_window"
|
|
14
|
+
require_relative "instagram_connect/ingest"
|
|
15
|
+
require_relative "instagram_connect/doctor"
|
|
16
|
+
|
|
17
|
+
# InstagramConnect connects a Rails app to Instagram over the official Meta
|
|
18
|
+
# Graph API: receive and reply to DMs and comments in real time via
|
|
19
|
+
# HMAC-verified webhooks, publish posts, and manage OAuth tokens.
|
|
20
|
+
#
|
|
21
|
+
# InstagramConnect.configure do |c|
|
|
22
|
+
# c.auth_path = :facebook_login
|
|
23
|
+
# c.app_id = Rails.application.credentials.dig(:instagram_connect, :app_id)
|
|
24
|
+
# c.app_secret = Rails.application.credentials.dig(:instagram_connect, :app_secret)
|
|
25
|
+
# c.verify_token = Rails.application.credentials.dig(:instagram_connect, :verify_token)
|
|
26
|
+
# end
|
|
27
|
+
module InstagramConnect
|
|
28
|
+
class << self
|
|
29
|
+
def configuration
|
|
30
|
+
@configuration ||= Configuration.new
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
attr_writer :configuration
|
|
34
|
+
|
|
35
|
+
def configure
|
|
36
|
+
yield(configuration)
|
|
37
|
+
configuration.validate!
|
|
38
|
+
configuration
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def reset!
|
|
42
|
+
@configuration = Configuration.new
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# simplecov:disable
|
|
48
|
+
if defined?(Rails::Engine)
|
|
49
|
+
require_relative "instagram_connect/engine"
|
|
50
|
+
elsif defined?(Rails::Railtie)
|
|
51
|
+
require_relative "instagram_connect/railtie"
|
|
52
|
+
end
|
|
53
|
+
# simplecov:enable
|
metadata
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: instagram_connect
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Kshitiz Sinha
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: rails
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '7.1'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '7.1'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: httparty
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0.21'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0.21'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: thor
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - ">="
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '1.0'
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '1.0'
|
|
54
|
+
description: 'A mountable Rails engine that connects your app to Instagram: receive
|
|
55
|
+
and reply to DMs and comments in real time over HMAC-verified webhooks, publish
|
|
56
|
+
posts, and manage OAuth tokens — using the official Instagram Graph API (Instagram-Login
|
|
57
|
+
or Facebook-Login), no unofficial automation.'
|
|
58
|
+
email:
|
|
59
|
+
- kshtzkr@gmail.com
|
|
60
|
+
executables:
|
|
61
|
+
- instagram_connect
|
|
62
|
+
extensions: []
|
|
63
|
+
extra_rdoc_files: []
|
|
64
|
+
files:
|
|
65
|
+
- ".github/workflows/ci.yml"
|
|
66
|
+
- ".rspec"
|
|
67
|
+
- CHANGELOG.md
|
|
68
|
+
- Gemfile
|
|
69
|
+
- LICENSE.txt
|
|
70
|
+
- MIT-LICENSE
|
|
71
|
+
- README.md
|
|
72
|
+
- Rakefile
|
|
73
|
+
- app/controllers/instagram_connect/application_controller.rb
|
|
74
|
+
- app/controllers/instagram_connect/comments_controller.rb
|
|
75
|
+
- app/controllers/instagram_connect/conversations_controller.rb
|
|
76
|
+
- app/controllers/instagram_connect/messages_controller.rb
|
|
77
|
+
- app/controllers/instagram_connect/oauth_controller.rb
|
|
78
|
+
- app/controllers/instagram_connect/posts_controller.rb
|
|
79
|
+
- app/controllers/instagram_connect/webhooks_controller.rb
|
|
80
|
+
- app/jobs/instagram_connect/application_job.rb
|
|
81
|
+
- app/jobs/instagram_connect/ingest_job.rb
|
|
82
|
+
- app/jobs/instagram_connect/refresh_tokens_job.rb
|
|
83
|
+
- app/jobs/instagram_connect/send_message_job.rb
|
|
84
|
+
- app/models/instagram_connect/account.rb
|
|
85
|
+
- app/models/instagram_connect/application_record.rb
|
|
86
|
+
- app/models/instagram_connect/comment.rb
|
|
87
|
+
- app/models/instagram_connect/conversation.rb
|
|
88
|
+
- app/models/instagram_connect/inbound_message.rb
|
|
89
|
+
- app/models/instagram_connect/message.rb
|
|
90
|
+
- app/views/instagram_connect/comments/_comment.html.erb
|
|
91
|
+
- app/views/instagram_connect/comments/index.html.erb
|
|
92
|
+
- app/views/instagram_connect/conversations/_composer.html.erb
|
|
93
|
+
- app/views/instagram_connect/conversations/_conversation.html.erb
|
|
94
|
+
- app/views/instagram_connect/conversations/_message.html.erb
|
|
95
|
+
- app/views/instagram_connect/conversations/index.html.erb
|
|
96
|
+
- app/views/instagram_connect/conversations/show.html.erb
|
|
97
|
+
- app/views/instagram_connect/posts/index.html.erb
|
|
98
|
+
- app/views/instagram_connect/posts/new.html.erb
|
|
99
|
+
- app/views/layouts/instagram_connect/application.html.erb
|
|
100
|
+
- bin/instagram_connect
|
|
101
|
+
- config/routes.rb
|
|
102
|
+
- docs/app_review_guide.md
|
|
103
|
+
- docs/auth_paths.md
|
|
104
|
+
- docs/roadmap.md
|
|
105
|
+
- lib/generators/instagram_connect/controllers_generator.rb
|
|
106
|
+
- lib/generators/instagram_connect/install/install_generator.rb
|
|
107
|
+
- lib/generators/instagram_connect/install/templates/create_instagram_connect_accounts.rb.tt
|
|
108
|
+
- lib/generators/instagram_connect/install/templates/create_instagram_connect_comments.rb.tt
|
|
109
|
+
- lib/generators/instagram_connect/install/templates/create_instagram_connect_conversations.rb.tt
|
|
110
|
+
- lib/generators/instagram_connect/install/templates/create_instagram_connect_inbound_messages.rb.tt
|
|
111
|
+
- lib/generators/instagram_connect/install/templates/create_instagram_connect_messages.rb.tt
|
|
112
|
+
- lib/generators/instagram_connect/install/templates/instagram_connect.rb.tt
|
|
113
|
+
- lib/generators/instagram_connect/views_generator.rb
|
|
114
|
+
- lib/instagram_connect.rb
|
|
115
|
+
- lib/instagram_connect/auth.rb
|
|
116
|
+
- lib/instagram_connect/auth/facebook_login.rb
|
|
117
|
+
- lib/instagram_connect/auth/instagram_login.rb
|
|
118
|
+
- lib/instagram_connect/auth/strategy.rb
|
|
119
|
+
- lib/instagram_connect/cli.rb
|
|
120
|
+
- lib/instagram_connect/client.rb
|
|
121
|
+
- lib/instagram_connect/configuration.rb
|
|
122
|
+
- lib/instagram_connect/connect.rb
|
|
123
|
+
- lib/instagram_connect/doctor.rb
|
|
124
|
+
- lib/instagram_connect/engine.rb
|
|
125
|
+
- lib/instagram_connect/errors.rb
|
|
126
|
+
- lib/instagram_connect/ingest.rb
|
|
127
|
+
- lib/instagram_connect/messaging_window.rb
|
|
128
|
+
- lib/instagram_connect/railtie.rb
|
|
129
|
+
- lib/instagram_connect/result.rb
|
|
130
|
+
- lib/instagram_connect/signature_verifier.rb
|
|
131
|
+
- lib/instagram_connect/version.rb
|
|
132
|
+
homepage: https://github.com/kshtzkr/instagram_connect
|
|
133
|
+
licenses:
|
|
134
|
+
- MIT
|
|
135
|
+
metadata:
|
|
136
|
+
allowed_push_host: https://rubygems.org
|
|
137
|
+
homepage_uri: https://github.com/kshtzkr/instagram_connect
|
|
138
|
+
source_code_uri: https://github.com/kshtzkr/instagram_connect/tree/main
|
|
139
|
+
changelog_uri: https://github.com/kshtzkr/instagram_connect/releases
|
|
140
|
+
bug_tracker_uri: https://github.com/kshtzkr/instagram_connect/issues
|
|
141
|
+
rubygems_mfa_required: 'true'
|
|
142
|
+
rdoc_options: []
|
|
143
|
+
require_paths:
|
|
144
|
+
- lib
|
|
145
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
146
|
+
requirements:
|
|
147
|
+
- - ">="
|
|
148
|
+
- !ruby/object:Gem::Version
|
|
149
|
+
version: '3.1'
|
|
150
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
151
|
+
requirements:
|
|
152
|
+
- - ">="
|
|
153
|
+
- !ruby/object:Gem::Version
|
|
154
|
+
version: '0'
|
|
155
|
+
requirements: []
|
|
156
|
+
rubygems_version: 4.0.3
|
|
157
|
+
specification_version: 4
|
|
158
|
+
summary: Instagram DMs, comments, and publishing for Rails via the official Meta Graph
|
|
159
|
+
API.
|
|
160
|
+
test_files: []
|