Skip to content

Commit

Permalink
Add sync command
Browse files Browse the repository at this point in the history
This command should be used to synchronise the podcast feed.
  • Loading branch information
gustavothecoder committed Oct 13, 2023
1 parent a3758c3 commit e90eec6
Show file tree
Hide file tree
Showing 10 changed files with 338 additions and 1 deletion.
8 changes: 7 additions & 1 deletion lib/pod/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,13 @@ def delete(podcast_id)
puts Pod::Outputs::Text::Delete.call(result)
end

desc "sync PODCAST_ID", "Sync the podcast."
# TODO
# desc "sync PODCAST_ID", "Synce the podcast."
# method_option :feed, type: :string, default: '', desc: "The feed that should be used."
def sync(podcast_id)
result = Pod::Commands::Sync.call(podcast_id)

puts Pod::Outputs::Text::Sync.call(result)
end
end
end
1 change: 1 addition & 0 deletions lib/pod/commands.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
require_relative "commands/archive"
require_relative "commands/dearchive"
require_relative "commands/delete"
require_relative "commands/sync"

module Pod
module Commands; end
Expand Down
4 changes: 4 additions & 0 deletions lib/pod/commands/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ def pod_db_dir
def parse_options(opts)
opts.select { |k, v| v != "" && v != [] }
end

def escape_double_quotes(str)
str.gsub("\"", "\"\"")
end
end
end
end
35 changes: 35 additions & 0 deletions lib/pod/commands/sync.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# frozen_string_literal: true

require_relative "../feed_parser"

module Pod
module Commands
class Sync < Base
def call(podcast_id)
db = Pod::Storage::SQL.new(db: pod_db_dir)
podcast = db.query(
"select feed from podcasts where id = #{podcast_id}",
Pod::Entities::Podcast
).first
return build_failure_response(details: :not_found) if podcast.nil?

parsed_feed = Pod::FeedParser.call(podcast.feed)
parsed_feed.episodes.each do |e|
db.execute <<-SQL
insert or ignore into episodes
(title, release_date, podcast_id, duration, link, external_id)
values (
"#{escape_double_quotes(e.title)}",
"#{escape_double_quotes(e.release_date)}",
#{podcast_id},
"#{escape_double_quotes(e.duration)}",
"#{escape_double_quotes(e.link)}",
"#{e.external_id}"
);
SQL
end
build_success_response(details: :podcast_synchronized)
end
end
end
end
1 change: 1 addition & 0 deletions lib/pod/outputs/text.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
require_relative "text/archive"
require_relative "text/dearchive"
require_relative "text/delete"
require_relative "text/sync"

module Pod
module Outputs
Expand Down
22 changes: 22 additions & 0 deletions lib/pod/outputs/text/sync.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true

module Pod
module Outputs
module Text
class Sync < ::Pod::Outputs::Base
def call
case @context[:details]
when :podcast_synchronized
<<~OUTPUT
Podcast successfully synchronized!
OUTPUT
when :not_found
<<~OUTPUT
Podcast not found
OUTPUT
end
end
end
end
end
end
147 changes: 147 additions & 0 deletions spec/fixtures/soft_skills_engineering_new_eps.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Soft Skills Engineering</title>
<description>It takes more than great code to be a great engineer. Soft Skills Engineering is a weekly advice podcast for software developers about the non-technical stuff that goes into being a great software developer.</description>
<itunes:summary>It takes more than great code to be a great engineer. Soft Skills Engineering is a weekly advice podcast for software developers about the non-technical stuff that goes into being a great software developer.</itunes:summary>
<atom:link href="https://softskills.audio/feed.xml" rel="self" type="application/rss+xml" />

<language>en</language>
<link>https://softskills.audio/</link>
<managingEditor>Jamison Dance and Dave Smith</managingEditor>
<webMaster>Jamison Dance and Dave Smith</webMaster>
<copyright>2016 Jamison Dance and Dave Smith</copyright>
<lastBuildDate>2023-09-11 12:00:00 +0000</lastBuildDate>
<itunes:explicit>no</itunes:explicit>
<image>
<link>https://softskills.audio</link>
<url>https://download.softskills.audio/sse-cover-art.png</url>
<title>Soft Skills Engineering</title>
</image>

<itunes:new-feed-url>https://softskills.audio/feed.xml</itunes:new-feed-url>
<itunes:subtitle>It takes more than great code to be a great engineer. Soft Skills Engineering is a weekly advice podcast for software developers about the non-technical stuff that goes into being a great software developer.</itunes:subtitle>
<itunes:author>Jamison Dance and Dave Smith</itunes:author>
<itunes:keywords></itunes:keywords>
<itunes:owner>
<itunes:name>Jamison Dance and Dave Smith</itunes:name>
<itunes:email>soft-skills-engineering@googlegroups.com</itunes:email>
</itunes:owner>
<itunes:image href="https://download.softskills.audio/sse-cover-art.png"></itunes:image>
<itunes:category text="Technology" />

<item>
<title>Episode 5: Developer Compensation</title>
<pubDate>Mon, 04 Apr 2016 19:00:00 +0000</pubDate>
<source url="https://softskills.audio">Soft Skills Engineering</source>
<guid isPermaLink="false">c7d52477-3b2f-4d69-a5a4-8f2911ea1dfe</guid>
<itunes:author></itunes:author>
<itunes:duration>25:33</itunes:duration>
<enclosure url="https://chrt.fm/track/FD81F6/dts.podtrac.com/redirect.mp3/download.softskills.audio/sse-005.mp3?source=rss" length="26148907" type="audio/mpeg"/>
<itunes:explicit>no</itunes:explicit>
<itunes:subtitle></itunes:subtitle>
<description>&lt;p&gt;In episode 5, Jamison and Dave answer this question:&lt;/p&gt;

&lt;p&gt;What are common ways developers are compensated? Do developers usually get a bonus? Stock options?&lt;/p&gt;

</description>
<link>https://softskills.audio/2016/04/04/episode-5-developer-compensation/</link>
</item>

<item>
<title>Episode 4: Should I build my personal brand?</title>
<pubDate>Thu, 31 Mar 2016 19:00:00 +0000</pubDate>
<source url="https://softskills.audio">Soft Skills Engineering</source>
<guid isPermaLink="false">45245e62-2797-4ac3-ada4-d550d12709c3</guid>
<itunes:author></itunes:author>
<itunes:duration>25:33</itunes:duration>
<enclosure url="https://chrt.fm/track/FD81F6/dts.podtrac.com/redirect.mp3/download.softskills.audio/sse-004.mp3?source=rss" length="27917611" type="audio/mpeg"/>
<itunes:explicit>no</itunes:explicit>
<itunes:subtitle></itunes:subtitle>
<description>&lt;p&gt;In episode 4, Jamison and Dave answer this question:&lt;/p&gt;

&lt;p&gt;I have heard a lot about “marketing myself” and my “personal brand”. For example, some people say I should be writing a blog post every week or creating lots of YouTube content. They talk about being a “thought leader”. I love building stuff as an engineer, and obviously I want to have a great job, so how important is this stuff?&lt;/p&gt;

</description>
<link>https://softskills.audio/2016/03/31/episode-4-should-i-build-my-personal-brand/</link>
</item>

<item>
<title>Episode 3: What to look for in a dev team</title>
<pubDate>Mon, 21 Mar 2016 19:00:00 +0000</pubDate>
<source url="https://softskills.audio">Soft Skills Engineering</source>
<guid isPermaLink="false">103dab3b-0da1-4f8e-883e-59552132c115</guid>
<itunes:author></itunes:author>
<itunes:duration>25:33</itunes:duration>
<enclosure url="https://dts.podtrac.com/redirect.mp3/download.softskills.audio/sse-003.mp3?source=rss" length="30740779" type="audio/mpeg"/>
<itunes:explicit>no</itunes:explicit>
<itunes:subtitle></itunes:subtitle>
<description>&lt;p&gt;In episode 3, Jamison and Dave answer two questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;What should I look for in a dev team?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I don’t get enough done at work. I work on a small team that has aggressive plans for developing its product, but I don’t feel like I get enough work done or move fast enough for the company.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

</description>
<link>https://softskills.audio/2016/03/21/episode-3-what-to-look-for-in-a-dev-team/</link>
</item>

<item>
<title>Episode 2: Influencing your team and dealing with anger</title>
<pubDate>Mon, 14 Mar 2016 19:00:00 +0000</pubDate>
<source url="https://softskills.audio">Soft Skills Engineering</source>
<guid isPermaLink="false">56d6dca2-d114-468a-953d-3f95b3048f59</guid>
<itunes:author></itunes:author>
<itunes:duration>25:33</itunes:duration>
<enclosure url="https://dts.podtrac.com/redirect.mp3/download.softskills.audio/sse-002.mp3?source=rss" length="34683307" type="audio/mpeg"/>
<itunes:explicit>no</itunes:explicit>
<itunes:subtitle></itunes:subtitle>
<description>&lt;p&gt;In episode 2, Jamison and Dave answer two questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;I work on a team, and I am not the team lead. I have lots of ideas for how to do things better. How can I influence my team without being the team lead, or without stepping on his or her shoes?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How do you deal with anger at work, both on the receiving and giving end?&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

</description>
<link>https://softskills.audio/2016/03/14/episode-2-influencing-your-team-and-dealing-with-anger/</link>
</item>

<item>
<title>Episode 1: Startup Opportunities and Switching Jobs</title>
<pubDate>Mon, 07 Mar 2016 19:00:00 +0000</pubDate>
<source url="https://softskills.audio">Soft Skills Engineering</source>
<guid isPermaLink="false">aea74a8a-e4b3-11e5-9016-001c4211514f</guid>
<itunes:author></itunes:author>
<itunes:duration>25:33</itunes:duration>
<enclosure url="https://dts.podtrac.com/redirect.mp3/download.softskills.audio/sse-001.mp3?source=rss" length="186254" type="audio/mpeg"/>
<itunes:explicit>no</itunes:explicit>
<itunes:subtitle></itunes:subtitle>
<description>&lt;p&gt;Welcome to Soft Skills Engineering, where we answer your questions about non-technical topics in software engineering. Come get some wisdom, or at least some wise cracks.&lt;/p&gt;

&lt;p&gt;In episode 1, Dave and Jamison answer two questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;I’m a developer who gets approached from time to time to work on new software ideas. While I find working on something new and intriguing I have no experience with business. How do I determine how legitimate these opportunities are?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;At my current job, our codebase is a few years old and we use an “older” javascript framework. In my spare time I’ve really really enjoyed using one of the newer paradigms and technical stacks and I wish I had more opportunity to get experience with these technologies. I don’t see a rewrite or even a migration any time soon for our codebase at this company and have been considering taking a job where I’d have opportunity to work with these newer technologies. This despite enjoying my coworkers, and lacking any major complaints at this company. On a scale from 1 to 10 how crazy am I for considering a job change?&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

</description>
<link>https://softskills.audio/2016/03/07/episode-1-startup-opportunities-and-switching-jobs/</link>
</item>

</channel>
</rss>
71 changes: 71 additions & 0 deletions spec/pod/commands/sync_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# frozen_string_literal: true

require_relative "../../support/test_helpers"

RSpec.describe Pod::Commands::Sync do
describe "#call", :init_pod do
context "when there are new episodes", :populate_db do
it "returns a success response and create records for the new episodes" do
db = Pod::Storage::SQL.new(db: TestHelpers::Path.db_dir)

before_episode_titles = db.query(
"select title from episodes where podcast_id = 1"
).map { |e| e["title"] }
expected_before_episode_titles = TestHelpers::Data
.soft_skills_engineering_episodes
.map { |e| e[:title] }
expect(before_episode_titles).to eq(expected_before_episode_titles)

allow(
Net::HTTP
).to receive(:get)
.with(URI("https://softskills.audio/feed.xml"))
.and_return(File.new("spec/fixtures/soft_skills_engineering_new_eps.xml").read)
result = described_class.call(1)

expect(result[:status]).to eq(:success)
expect(result[:details]).to eq(:podcast_synchronized)
after_episode_titles = db.query(
"select title from episodes where podcast_id = 1"
).map { |e| e["title"] }
expected_after_episode_titles = TestHelpers::Data
.all_soft_skills_engineering_episodes
.map { |e| e[:title] }
expect(after_episode_titles).to eq(expected_after_episode_titles)
end
end

context "when the podcast is already up to date", :populate_db do
it "returns a success response, but does not create any records" do
db = Pod::Storage::SQL.new(db: TestHelpers::Path.db_dir)

before_episode_titles = db.query(
"select title from episodes where podcast_id = 1"
).map { |e| e["title"] }

allow(
Net::HTTP
).to receive(:get)
.with(URI("https://softskills.audio/feed.xml"))
.and_return(File.new("spec/fixtures/soft_skills_engineering.xml").read)
result = described_class.call(1)

expect(result[:status]).to eq(:success)
expect(result[:details]).to eq(:podcast_synchronized)
after_episode_titles = db.query(
"select title from episodes where podcast_id = 1"
).map { |e| e["title"] }
expect(after_episode_titles).to eq(before_episode_titles)
end
end

context "when the podcast is not found" do
it "returns a failure response and does not create any records" do
result = described_class.call(1)

expect(result[:status]).to eq(:failure)
expect(result[:details]).to eq(:not_found)
end
end
end
end
31 changes: 31 additions & 0 deletions spec/pod/outputs/text/sync_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# frozen_string_literal: true

RSpec.describe Pod::Outputs::Text::Sync do
describe "#call" do
context "when the podcast is successfully synchronized" do
it "generates the correct message" do
response = described_class.new(status: :success, details: :podcast_synchronized)
expected_output = <<~OUTPUT
Podcast successfully synchronized!
OUTPUT

msg = response.call

expect(msg).to eq(expected_output)
end
end

context "when the podcast is not found" do
it "generates the correct message" do
response = described_class.new(status: :success, details: :not_found)
expected_output = <<~OUTPUT
Podcast not found
OUTPUT

msg = response.call

expect(msg).to eq(expected_output)
end
end
end
end
19 changes: 19 additions & 0 deletions spec/support/test_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,25 @@ def soft_skills_engineering_episodes
]
end

def all_soft_skills_engineering_episodes
soft_skills_engineering_episodes + [
{
title: "Episode 4: Should I build my personal brand?",
release_date: "2016-03-31T19:00:00Z",
duration: "25:33",
link: "https://softskills.audio/2016/03/31/episode-4-should-i-build-my-personal-brand/",
external_id: "45245e62-2797-4ac3-ada4-d550d12709c3"
},
{
title: "Episode 5: Developer Compensation",
release_date: "2016-04-04T19:00:00Z",
duration: "25:33",
link: "https://softskills.audio/2016/04/04/episode-5-developer-compensation/",
external_id: "c7d52477-3b2f-4d69-a5a4-8f2911ea1dfe"
}
]
end

def fabio_akita
{
name: "Akitando",
Expand Down

0 comments on commit e90eec6

Please sign in to comment.