Skip to content

Commit

Permalink
Merge pull request #39 from realstorypro/twitter-send
Browse files Browse the repository at this point in the history
Adding ability to send tweets
  • Loading branch information
Leonid Medovyy committed May 16, 2023
2 parents 32b007a + 427cc79 commit d5179d9
Show file tree
Hide file tree
Showing 10 changed files with 151 additions and 80 deletions.
34 changes: 34 additions & 0 deletions app/jobs/discussions/publish_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
module Discussions
class PublishJob < ApplicationJob
queue_as :default
MAX_STORIES_PUBLISHED_AT_A_TIME = 1

def perform(*args)
ready_discussions = Discussion.ready_to_upload

todays_uploaded_discussions_by_subtopic = Discussion.published_today_and_uploaded
.group('sub_topics.id')
.select('sub_topics.*, COUNT(discussions.id) AS discussions_count')
.map do |sub_topic|
{
sub_topic: sub_topic,
discussions_count: sub_topic.discussions_count
}
end

subtopics_with_max_discussions = todays_uploaded_discussions_by_subtopic.select do |hash|
hash[:discussions_count] >= hash[:sub_topic].max_stories_per_day
end

# Extract subtopic_ids from subtopics_with_max_discussions
subtopic_ids_with_max_discussions = subtopics_with_max_discussions.map { |hash| hash[:sub_topic].id }

# Exclude discussions that have a sub_topic_id in subtopic_ids_with_max_discussions
ready_discussions = ready_discussions.where.not(stories: { sub_topic_id: subtopic_ids_with_max_discussions })

ready_discussions.sample(MAX_STORIES_PUBLISHED_AT_A_TIME).each do |discussion|
StoryPro::CreateDiscussionJob.perform_now(discussion:)
end
end
end
end
43 changes: 0 additions & 43 deletions app/jobs/dispense_job.rb

This file was deleted.

29 changes: 2 additions & 27 deletions app/jobs/publish_job.rb
Original file line number Diff line number Diff line change
@@ -1,32 +1,7 @@
class PublishJob < ApplicationJob
queue_as :default
MAX_STORIES_PUBLISHED_AT_A_TIME = 1

def perform(*args)
ready_discussions = Discussion.ready_to_upload

todays_uploaded_discussions_by_subtopic = Discussion.published_today_and_uploaded
.group('sub_topics.id')
.select('sub_topics.*, COUNT(discussions.id) AS discussions_count')
.map do |sub_topic|
{
sub_topic: sub_topic,
discussions_count: sub_topic.discussions_count
}
end

subtopics_with_max_discussions = todays_uploaded_discussions_by_subtopic.select do |hash|
hash[:discussions_count] >= hash[:sub_topic].max_stories_per_day
end

# Extract subtopic_ids from subtopics_with_max_discussions
subtopic_ids_with_max_discussions = subtopics_with_max_discussions.map { |hash| hash[:sub_topic].id }

# Exclude discussions that have a sub_topic_id in subtopic_ids_with_max_discussions
ready_discussions = ready_discussions.where.not(stories: { sub_topic_id: subtopic_ids_with_max_discussions })

ready_discussions.sample(MAX_STORIES_PUBLISHED_AT_A_TIME).each do |discussion|
StoryPro::CreateDiscussionJob.perform_now(discussion:)
end
def perform(*_args)
Discussions::PublishJob.perform_now
end
end
2 changes: 1 addition & 1 deletion app/jobs/tweets/process_twitter_stems_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ class Tweets::ProcessTwitterStemsJob < ApplicationJob
queue_as :default

def perform(*args)
Discussion.ready_for_tweets.each do |discussion|
Discussion.ready_to_make_tweets.each do |discussion|
Tweets::MakeStemJob.perform_now(discussion:)
end
end
Expand Down
10 changes: 10 additions & 0 deletions app/jobs/tweets/publish_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class Tweets::PublishJob < ApplicationJob
queue_as :default
MAX_TWEETS_PUBLISHED_AT_A_TIME = 1

def perform(*args)
Discussion.ready_to_upload_tweets.sample(MAX_TWEETS_PUBLISHED_AT_A_TIME).each do |discussion|
Tweets::PublishTweetJob.perform_now(discussion:)
end
end
end
32 changes: 32 additions & 0 deletions app/jobs/tweets/publish_tweet_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
class Tweets::PublishTweetJob < ApplicationJob
queue_as :default

def perform(discussion:)
return if discussion.tweet.uploaded

story = discussion.story
tweet = discussion.tweet

tweet_text = JSON.parse(tweet.stem)['tweet']
card_image = tweet.discussion.story.imaginations.where(aspect_ratio: :card).sample(1)
card_image_url = "https://ucarecdn.com/#{card_image.last.uploadcare.last['uuid']}/"


story_pro_discussion = StoryPro.get_discussion(discussion.story_pro_id)
discussion_slug = story_pro_discussion["entry"]["slug"]
category_slug = get_story_pro_category_slug(story)

discussion_url = "#{ENV['STORYPRO_URL']}/discussions/#{category_slug}/#{discussion_slug}"

full_tweet = "#{tweet_text} #{discussion_url}"
Ayrshare.post_message(post: full_tweet, platforms: ['twitter'], media_urls: [card_image_url])

tweet.update(uploaded: true)
end

def get_story_pro_category_slug(story)
story_pro_categories = StoryPro.get_categories
found_story_pro_category = story_pro_categories.find { |c| c["id"] == story.sub_topic.storypro_category_id }
found_story_pro_category['slug']
end
end
33 changes: 33 additions & 0 deletions app/lib/ayrshare.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
require 'httparty'
require 'json'

module Ayrshare
class Configuration
attr_accessor :api_key

def initialize
@api_key = nil
end
end

class << self
attr_accessor :configuration
end

def self.configure
self.configuration ||= Configuration.new
yield(configuration)
end

def self.post_message(post:, platforms:, media_urls: [])
url = "https://app.ayrshare.com/api/post"
headers = { 'Authorization' => "Bearer #{configuration.api_key}" }
body = { post:, platforms:, mediaUrls: [media_urls] }

response = HTTParty.post(url, headers:, body:)

raise "Error: #{response.code} - #{response.body}" unless response.code == 200

JSON.parse(response.body)
end
end
27 changes: 26 additions & 1 deletion app/models/discussion.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,25 @@
# updated_at :datetime not null
# published_at :datetime
# story_pro_id :integer

################ logic #################
# - the `processed` tag is used to determine if the stem has been created by the ai.
# * it is set to true in discussions/make_stem_job.rb
# * if it checked against in the process_discussion_stems_job.rb
#
# - the `invalid_json` tag is set to true if the ai fails to create a stem for the discussion.
# * it is set to true in discussions/make_stem_job.rb
#
# - the `uploaded` tag is used to determine if the discussion has been uploaded to StoryPRO
# * it is set to true in create_discussion_job.rb
#
# - the `published_at` tag is the date when the item was published to StoryPRO
# * it is set to true in create_discussion_job.rb
#
# - the `story_pro_id` is the id of the discussion in StoryPRO
# * it is set to true in create_discussion_job.rb
########################################

class Discussion < ApplicationRecord
belongs_to :story
has_one :tweet, dependent: :destroy
Expand All @@ -27,10 +45,17 @@ class Discussion < ApplicationRecord
published_at: Time.now.utc.beginning_of_day..Time.now.utc.end_of_day)
}

scope :ready_for_tweets, lambda {
scope :ready_to_make_tweets, lambda {
joins(story: :sub_topic)
.where(processed: true, invalid_json: false)
.left_outer_joins(:tweet)
.where(tweets: { discussion_id: nil })
}

scope :ready_to_upload_tweets, lambda {
joins(story: :sub_topic)
.where(uploaded: true)
.joins(:tweet)
.where(tweets: { uploaded: false })
}
end
16 changes: 8 additions & 8 deletions app/models/story.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@
# invalid_images :boolean default(FALSE)
#

################ LOGIC #################
# - The `processed` tag is used to determine if the stem has been created by the AI.
# * It is set to true in make_stem_job.rb
# * If it checked against in the process_stories_job.rb
################ logic #################
# - the `processed` tag is used to determine if the stem has been created by the ai.
# * it is set to true in stories/make_stem_job.rb
# * if it checked against in the process_story_stems_job.rb
#
# - The `invalid_json` tag is set to true if the AI fails to create a stem for the story.
# * It is set to true in make_stem_job.rb
# - the `invalid_json` tag is set to true if the ai fails to create a stem for the story.
# * it is set to true in stories/make_stem_job.rb
#
# - The `invalid_images` tag is set to true if the AI fails to create images ideas for ANY of the images.
# * It is set to true in create_image_idea_job.rb
# - the `invalid_images` tag is set to true if the ai fails to create images ideas for any of the images.
# * it is set to true in create_image_idea_job.rb
########################################

class Story < ApplicationRecord
Expand Down
5 changes: 5 additions & 0 deletions config/initializers/ayrshare.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
require 'ayrshare'

Ayrshare.configure do |config|
config.api_key = ENV['AYRSHARE_API_KEY']
end

0 comments on commit d5179d9

Please sign in to comment.