Browse Source

ytautodownloader

Stephen 3 months ago
commit
51131403fc
111 changed files with 9513 additions and 0 deletions
  1. 1 0
      .browserslistrc
  2. 34 0
      .gitignore
  3. 1 0
      .ruby-version
  4. 56 0
      Gemfile
  5. 234 0
      Gemfile.lock
  6. 24 0
      README.md
  7. 6 0
      Rakefile
  8. 2 0
      app/assets/config/manifest.js
  9. 0 0
      app/assets/images/.keep
  10. 19 0
      app/assets/stylesheets/application.css
  11. 3 0
      app/assets/stylesheets/subscriptions.scss
  12. 3 0
      app/assets/stylesheets/videos.scss
  13. 4 0
      app/channels/application_cable/channel.rb
  14. 4 0
      app/channels/application_cable/connection.rb
  15. 2 0
      app/controllers/application_controller.rb
  16. 0 0
      app/controllers/concerns/.keep
  17. 22 0
      app/controllers/subscriptions_controller.rb
  18. 14 0
      app/controllers/videos_controller.rb
  19. 2 0
      app/helpers/application_helper.rb
  20. 2 0
      app/helpers/subscriptions_helper.rb
  21. 2 0
      app/helpers/videos_helper.rb
  22. 6 0
      app/javascript/channels/consumer.js
  23. 5 0
      app/javascript/channels/index.js
  24. 17 0
      app/javascript/packs/application.js
  25. 7 0
      app/jobs/application_job.rb
  26. 4 0
      app/mailers/application_mailer.rb
  27. 3 0
      app/models/application_record.rb
  28. 0 0
      app/models/concerns/.keep
  29. 3 0
      app/models/subscription.rb
  30. 19 0
      app/models/video.rb
  31. 20 0
      app/views/layouts/application.html.erb
  32. 13 0
      app/views/layouts/mailer.html.erb
  33. 1 0
      app/views/layouts/mailer.text.erb
  34. 4 0
      app/views/subscriptions/index.html.erb
  35. 5 0
      app/views/subscriptions/new.html.erb
  36. 15 0
      app/views/videos/index.html.erb
  37. 7 0
      app/views/videos/show.html.erb
  38. 72 0
      babel.config.js
  39. 105 0
      bin/bundle
  40. 9 0
      bin/rails
  41. 9 0
      bin/rake
  42. 36 0
      bin/setup
  43. 17 0
      bin/spring
  44. 18 0
      bin/webpack
  45. 18 0
      bin/webpack-dev-server
  46. 11 0
      bin/yarn
  47. 5 0
      config.ru
  48. 19 0
      config/application.rb
  49. 4 0
      config/boot.rb
  50. 10 0
      config/cable.yml
  51. 1 0
      config/credentials.yml.enc
  52. 85 0
      config/database.yml
  53. 5 0
      config/environment.rb
  54. 62 0
      config/environments/development.rb
  55. 112 0
      config/environments/production.rb
  56. 48 0
      config/environments/test.rb
  57. 8 0
      config/initializers/application_controller_renderer.rb
  58. 14 0
      config/initializers/assets.rb
  59. 7 0
      config/initializers/backtrace_silencers.rb
  60. 30 0
      config/initializers/content_security_policy.rb
  61. 5 0
      config/initializers/cookies_serializer.rb
  62. 4 0
      config/initializers/filter_parameter_logging.rb
  63. 16 0
      config/initializers/inflections.rb
  64. 5 0
      config/initializers/mime_types.rb
  65. 19 0
      config/initializers/scheduler.rb
  66. 14 0
      config/initializers/wrap_parameters.rb
  67. 33 0
      config/locales/en.yml
  68. 38 0
      config/puma.rb
  69. 5 0
      config/routes.rb
  70. 6 0
      config/spring.rb
  71. 34 0
      config/storage.yml
  72. 5 0
      config/webpack/development.js
  73. 3 0
      config/webpack/environment.js
  74. 5 0
      config/webpack/production.js
  75. 5 0
      config/webpack/test.js
  76. 96 0
      config/webpacker.yml
  77. 8 0
      db/migrate/20191210031133_create_subscriptions.rb
  78. 14 0
      db/migrate/20191210122329_create_videos.rb
  79. 36 0
      db/schema.rb
  80. 7 0
      db/seeds.rb
  81. 0 0
      lib/assets/.keep
  82. 0 0
      lib/tasks/.keep
  83. 81 0
      lib/youtube.rb
  84. 0 0
      log/.keep
  85. 41 0
      other/scraper.py
  86. 15 0
      package.json
  87. 12 0
      postcss.config.js
  88. 67 0
      public/404.html
  89. 67 0
      public/422.html
  90. 66 0
      public/500.html
  91. 0 0
      public/apple-touch-icon-precomposed.png
  92. 0 0
      public/apple-touch-icon.png
  93. 0 0
      public/favicon.ico
  94. 1 0
      public/robots.txt
  95. 0 0
      storage/.keep
  96. 5 0
      test/application_system_test_case.rb
  97. 11 0
      test/channels/application_cable/connection_test.rb
  98. 0 0
      test/controllers/.keep
  99. 7 0
      test/controllers/subscriptions_controller_test.rb
  100. 7 0
      test/controllers/videos_controller_test.rb
  101. 0 0
      test/fixtures/.keep
  102. 0 0
      test/fixtures/files/.keep
  103. 0 0
      test/helpers/.keep
  104. 0 0
      test/integration/.keep
  105. 0 0
      test/mailers/.keep
  106. 0 0
      test/models/.keep
  107. 0 0
      test/system/.keep
  108. 13 0
      test/test_helper.rb
  109. 0 0
      tmp/.keep
  110. 0 0
      vendor/.keep
  111. 7493 0
      yarn.lock

+ 1 - 0
.browserslistrc

@ -0,0 +1 @@
1
defaults

+ 34 - 0
.gitignore

@ -0,0 +1,34 @@
1
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
2
#
3
# If you find yourself ignoring temporary files generated by your text editor
4
# or operating system, you probably want to add a global ignore instead:
5
#   git config --global core.excludesfile '~/.gitignore_global'
6
7
# Ignore bundler config.
8
/.bundle
9
10
# Ignore all logfiles and tempfiles.
11
/log/*
12
/tmp/*
13
!/log/.keep
14
!/tmp/.keep
15
16
# Ignore uploaded files in development.
17
/storage/*
18
!/storage/.keep
19
20
/public/assets
21
.byebug_history
22
23
# Ignore master key for decrypting credentials and more.
24
/config/master.key
25
26
/public/packs
27
/public/packs-test
28
/node_modules
29
/yarn-error.log
30
yarn-debug.log*
31
.yarn-integrity
32
33
#Ignore videos
34
/public/videos/*

+ 1 - 0
.ruby-version

@ -0,0 +1 @@
1
ruby-2.6.4

+ 56 - 0
Gemfile

@ -0,0 +1,56 @@
1
source 'https://rubygems.org'
2
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
3
4
ruby '2.6.4'
5
6
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
7
gem 'rails', '~> 6.0.1'
8
# Use postgresql as the database for Active Record
9
gem 'pg', '>= 0.18', '< 2.0'
10
# Use Puma as the app server
11
gem 'puma', '~> 4.1'
12
# Use SCSS for stylesheets
13
gem 'sass-rails', '>= 6'
14
# Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker
15
gem 'webpacker', '~> 4.0'
16
# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
17
gem 'turbolinks', '~> 5'
18
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
19
gem 'jbuilder', '~> 2.7'
20
# Use Redis adapter to run Action Cable in production
21
# gem 'redis', '~> 4.0'
22
# Use Active Model has_secure_password
23
# gem 'bcrypt', '~> 3.1.7'
24
25
# Use Active Storage variant
26
# gem 'image_processing', '~> 1.2'
27
28
# Reduces boot times through caching; required in config/boot.rb
29
gem 'bootsnap', '>= 1.4.2', require: false
30
31
group :development, :test do
32
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
33
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
34
end
35
36
group :development do
37
  # Access an interactive console on exception pages or by calling 'console' anywhere in the code.
38
  gem 'web-console', '>= 3.3.0'
39
  gem 'listen', '>= 3.0.5', '< 3.2'
40
  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
41
  gem 'spring'
42
  gem 'spring-watcher-listen', '~> 2.0.0'
43
end
44
45
group :test do
46
  # Adds support for Capybara system testing and selenium driver
47
  gem 'capybara', '>= 2.15'
48
  gem 'selenium-webdriver'
49
  # Easy installation and use of web drivers to run system tests with browsers
50
  gem 'webdrivers'
51
end
52
53
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
54
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
55
56
gem 'rufus-scheduler'

+ 234 - 0
Gemfile.lock

@ -0,0 +1,234 @@
1
GEM
2
  remote: https://rubygems.org/
3
  specs:
4
    actioncable (6.0.1)
5
      actionpack (= 6.0.1)
6
      nio4r (~> 2.0)
7
      websocket-driver (>= 0.6.1)
8
    actionmailbox (6.0.1)
9
      actionpack (= 6.0.1)
10
      activejob (= 6.0.1)
11
      activerecord (= 6.0.1)
12
      activestorage (= 6.0.1)
13
      activesupport (= 6.0.1)
14
      mail (>= 2.7.1)
15
    actionmailer (6.0.1)
16
      actionpack (= 6.0.1)
17
      actionview (= 6.0.1)
18
      activejob (= 6.0.1)
19
      mail (~> 2.5, >= 2.5.4)
20
      rails-dom-testing (~> 2.0)
21
    actionpack (6.0.1)
22
      actionview (= 6.0.1)
23
      activesupport (= 6.0.1)
24
      rack (~> 2.0)
25
      rack-test (>= 0.6.3)
26
      rails-dom-testing (~> 2.0)
27
      rails-html-sanitizer (~> 1.0, >= 1.2.0)
28
    actiontext (6.0.1)
29
      actionpack (= 6.0.1)
30
      activerecord (= 6.0.1)
31
      activestorage (= 6.0.1)
32
      activesupport (= 6.0.1)
33
      nokogiri (>= 1.8.5)
34
    actionview (6.0.1)
35
      activesupport (= 6.0.1)
36
      builder (~> 3.1)
37
      erubi (~> 1.4)
38
      rails-dom-testing (~> 2.0)
39
      rails-html-sanitizer (~> 1.1, >= 1.2.0)
40
    activejob (6.0.1)
41
      activesupport (= 6.0.1)
42
      globalid (>= 0.3.6)
43
    activemodel (6.0.1)
44
      activesupport (= 6.0.1)
45
    activerecord (6.0.1)
46
      activemodel (= 6.0.1)
47
      activesupport (= 6.0.1)
48
    activestorage (6.0.1)
49
      actionpack (= 6.0.1)
50
      activejob (= 6.0.1)
51
      activerecord (= 6.0.1)
52
      marcel (~> 0.3.1)
53
    activesupport (6.0.1)
54
      concurrent-ruby (~> 1.0, >= 1.0.2)
55
      i18n (>= 0.7, < 2)
56
      minitest (~> 5.1)
57
      tzinfo (~> 1.1)
58
      zeitwerk (~> 2.2)
59
    addressable (2.7.0)
60
      public_suffix (>= 2.0.2, < 5.0)
61
    bindex (0.8.1)
62
    bootsnap (1.4.5)
63
      msgpack (~> 1.0)
64
    builder (3.2.3)
65
    byebug (11.0.1)
66
    capybara (3.29.0)
67
      addressable
68
      mini_mime (>= 0.1.3)
69
      nokogiri (~> 1.8)
70
      rack (>= 1.6.0)
71
      rack-test (>= 0.6.3)
72
      regexp_parser (~> 1.5)
73
      xpath (~> 3.2)
74
    childprocess (3.0.0)
75
    concurrent-ruby (1.1.5)
76
    crass (1.0.5)
77
    erubi (1.9.0)
78
    et-orbi (1.2.2)
79
      tzinfo
80
    ffi (1.11.3)
81
    fugit (1.3.3)
82
      et-orbi (~> 1.1, >= 1.1.8)
83
      raabro (~> 1.1)
84
    globalid (0.4.2)
85
      activesupport (>= 4.2.0)
86
    i18n (1.7.0)
87
      concurrent-ruby (~> 1.0)
88
    jbuilder (2.9.1)
89
      activesupport (>= 4.2.0)
90
    listen (3.1.5)
91
      rb-fsevent (~> 0.9, >= 0.9.4)
92
      rb-inotify (~> 0.9, >= 0.9.7)
93
      ruby_dep (~> 1.2)
94
    loofah (2.4.0)
95
      crass (~> 1.0.2)
96
      nokogiri (>= 1.5.9)
97
    mail (2.7.1)
98
      mini_mime (>= 0.1.1)
99
    marcel (0.3.3)
100
      mimemagic (~> 0.3.2)
101
    method_source (0.9.2)
102
    mimemagic (0.3.3)
103
    mini_mime (1.0.2)
104
    mini_portile2 (2.4.0)
105
    minitest (5.13.0)
106
    msgpack (1.3.1)
107
    nio4r (2.5.2)
108
    nokogiri (1.10.7)
109
      mini_portile2 (~> 2.4.0)
110
    pg (1.1.4)
111
    public_suffix (4.0.1)
112
    puma (4.3.1)
113
      nio4r (~> 2.0)
114
    raabro (1.1.6)
115
    rack (2.0.7)
116
    rack-proxy (0.6.5)
117
      rack
118
    rack-test (1.1.0)
119
      rack (>= 1.0, < 3)
120
    rails (6.0.1)
121
      actioncable (= 6.0.1)
122
      actionmailbox (= 6.0.1)
123
      actionmailer (= 6.0.1)
124
      actionpack (= 6.0.1)
125
      actiontext (= 6.0.1)
126
      actionview (= 6.0.1)
127
      activejob (= 6.0.1)
128
      activemodel (= 6.0.1)
129
      activerecord (= 6.0.1)
130
      activestorage (= 6.0.1)
131
      activesupport (= 6.0.1)
132
      bundler (>= 1.3.0)
133
      railties (= 6.0.1)
134
      sprockets-rails (>= 2.0.0)
135
    rails-dom-testing (2.0.3)
136
      activesupport (>= 4.2.0)
137
      nokogiri (>= 1.6)
138
    rails-html-sanitizer (1.3.0)
139
      loofah (~> 2.3)
140
    railties (6.0.1)
141
      actionpack (= 6.0.1)
142
      activesupport (= 6.0.1)
143
      method_source
144
      rake (>= 0.8.7)
145
      thor (>= 0.20.3, < 2.0)
146
    rake (13.0.1)
147
    rb-fsevent (0.10.3)
148
    rb-inotify (0.10.0)
149
      ffi (~> 1.0)
150
    regexp_parser (1.6.0)
151
    ruby_dep (1.5.0)
152
    rubyzip (2.0.0)
153
    rufus-scheduler (3.6.0)
154
      fugit (~> 1.1, >= 1.1.6)
155
    sass-rails (6.0.0)
156
      sassc-rails (~> 2.1, >= 2.1.1)
157
    sassc (2.2.1)
158
      ffi (~> 1.9)
159
    sassc-rails (2.1.2)
160
      railties (>= 4.0.0)
161
      sassc (>= 2.0)
162
      sprockets (> 3.0)
163
      sprockets-rails
164
      tilt
165
    selenium-webdriver (3.142.6)
166
      childprocess (>= 0.5, < 4.0)
167
      rubyzip (>= 1.2.2)
168
    spring (2.1.0)
169
    spring-watcher-listen (2.0.1)
170
      listen (>= 2.7, < 4.0)
171
      spring (>= 1.2, < 3.0)
172
    sprockets (4.0.0)
173
      concurrent-ruby (~> 1.0)
174
      rack (> 1, < 3)
175
    sprockets-rails (3.2.1)
176
      actionpack (>= 4.0)
177
      activesupport (>= 4.0)
178
      sprockets (>= 3.0.0)
179
    thor (0.20.3)
180
    thread_safe (0.3.6)
181
    tilt (2.0.10)
182
    turbolinks (5.2.1)
183
      turbolinks-source (~> 5.2)
184
    turbolinks-source (5.2.0)
185
    tzinfo (1.2.5)
186
      thread_safe (~> 0.1)
187
    web-console (4.0.1)
188
      actionview (>= 6.0.0)
189
      activemodel (>= 6.0.0)
190
      bindex (>= 0.4.0)
191
      railties (>= 6.0.0)
192
    webdrivers (4.1.3)
193
      nokogiri (~> 1.6)
194
      rubyzip (>= 1.3.0)
195
      selenium-webdriver (>= 3.0, < 4.0)
196
    webpacker (4.2.2)
197
      activesupport (>= 4.2)
198
      rack-proxy (>= 0.6.1)
199
      railties (>= 4.2)
200
    websocket-driver (0.7.1)
201
      websocket-extensions (>= 0.1.0)
202
    websocket-extensions (0.1.4)
203
    xpath (3.2.0)
204
      nokogiri (~> 1.8)
205
    zeitwerk (2.2.2)
206
207
PLATFORMS
208
  ruby
209
210
DEPENDENCIES
211
  bootsnap (>= 1.4.2)
212
  byebug
213
  capybara (>= 2.15)
214
  jbuilder (~> 2.7)
215
  listen (>= 3.0.5, < 3.2)
216
  pg (>= 0.18, < 2.0)
217
  puma (~> 4.1)
218
  rails (~> 6.0.1)
219
  rufus-scheduler
220
  sass-rails (>= 6)
221
  selenium-webdriver
222
  spring
223
  spring-watcher-listen (~> 2.0.0)
224
  turbolinks (~> 5)
225
  tzinfo-data
226
  web-console (>= 3.3.0)
227
  webdrivers
228
  webpacker (~> 4.0)
229
230
RUBY VERSION
231
   ruby 2.6.4p104
232
233
BUNDLED WITH
234
   2.0.0

+ 24 - 0
README.md

@ -0,0 +1,24 @@
1
# README
2
3
This README would normally document whatever steps are necessary to get the
4
application up and running.
5
6
Things you may want to cover:
7
8
* Ruby version
9
10
* System dependencies
11
12
* Configuration
13
14
* Database creation
15
16
* Database initialization
17
18
* How to run the test suite
19
20
* Services (job queues, cache servers, search engines, etc.)
21
22
* Deployment instructions
23
24
* ...

+ 6 - 0
Rakefile

@ -0,0 +1,6 @@
1
# Add your own tasks in files placed in lib/tasks ending in .rake,
2
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
4
require_relative 'config/application'
5
6
Rails.application.load_tasks

+ 2 - 0
app/assets/config/manifest.js

@ -0,0 +1,2 @@
1
//= link_tree ../images
2
//= link_directory ../stylesheets .css

+ 0 - 0
app/assets/images/.keep


+ 19 - 0
app/assets/stylesheets/application.css

@ -0,0 +1,19 @@
1
/*
2
 * This is a manifest file that'll be compiled into application.css, which will include all the files
3
 * listed below.
4
 *
5
 * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's
6
 * vendor/assets/stylesheets directory can be referenced here using a relative path.
7
 *
8
 * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
 * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
 * files in this directory. Styles in this file should be added after the last require_* statement.
11
 * It is generally better to create a new file per style scope.
12
 *
13
 *= require_tree .
14
 *= require_self
15
 */
16
.centertext {
17
	width: 40%;
18
	margin: 0 auto;
19
}

+ 3 - 0
app/assets/stylesheets/subscriptions.scss

@ -0,0 +1,3 @@
1
// Place all the styles related to the subscriptions controller here.
2
// They will automatically be included in application.css.
3
// You can use Sass (SCSS) here: https://sass-lang.com/

+ 3 - 0
app/assets/stylesheets/videos.scss

@ -0,0 +1,3 @@
1
// Place all the styles related to the videos controller here.
2
// They will automatically be included in application.css.
3
// You can use Sass (SCSS) here: https://sass-lang.com/

+ 4 - 0
app/channels/application_cable/channel.rb

@ -0,0 +1,4 @@
1
module ApplicationCable
2
  class Channel < ActionCable::Channel::Base
3
  end
4
end

+ 4 - 0
app/channels/application_cable/connection.rb

@ -0,0 +1,4 @@
1
module ApplicationCable
2
  class Connection < ActionCable::Connection::Base
3
  end
4
end

+ 2 - 0
app/controllers/application_controller.rb

@ -0,0 +1,2 @@
1
class ApplicationController < ActionController::Base
2
end

+ 0 - 0
app/controllers/concerns/.keep


+ 22 - 0
app/controllers/subscriptions_controller.rb

@ -0,0 +1,22 @@
1
class SubscriptionsController < ApplicationController
2
  def index
3
    @subs = Subscription.all
4
  end
5
6
  def new
7
    @sub = Subscription.new
8
  end
9
10
  def create
11
    html = Net::HTTP.get(URI.parse(params[:subscription][:url]))
12
    channel_id = Nokogiri::HTML(html).at('link[rel="canonical"]')['href'].split('/')[-1]
13
    #begin
14
    #  channel_id = html.match(/channel_id=\w*"/)[0][11...-1]
15
    #rescue
16
    #  channel_id = params[:subscription][:url].split('/')[-1]
17
    #end
18
    
19
    @sub = Subscription.create(url: channel_id)
20
    redirect_to subscriptions_path
21
  end
22
end

+ 14 - 0
app/controllers/videos_controller.rb

@ -0,0 +1,14 @@
1
class VideosController < ApplicationController
2
  def index
3
    @p = params[:p].try(:to_i) || 1
4
    @vids = Video.order(published_date: :desc).preload(:subscription)
5
              .limit(11).offset(10 * (@p - 1)).all
6
    @has_next = @vids.size > 10
7
    @vids = @vids[0...10]
8
    @has_prev = @p > 1
9
  end
10
11
  def show
12
    @vid = Video.find(params[:id])
13
  end
14
end

+ 2 - 0
app/helpers/application_helper.rb

@ -0,0 +1,2 @@
1
module ApplicationHelper
2
end

+ 2 - 0
app/helpers/subscriptions_helper.rb

@ -0,0 +1,2 @@
1
module SubscriptionsHelper
2
end

+ 2 - 0
app/helpers/videos_helper.rb

@ -0,0 +1,2 @@
1
module VideosHelper
2
end

+ 6 - 0
app/javascript/channels/consumer.js

@ -0,0 +1,6 @@
1
// Action Cable provides the framework to deal with WebSockets in Rails.
2
// You can generate new channels where WebSocket features live using the `rails generate channel` command.
3
4
import { createConsumer } from "@rails/actioncable"
5
6
export default createConsumer()

+ 5 - 0
app/javascript/channels/index.js

@ -0,0 +1,5 @@
1
// Load all the channels within this directory and all subdirectories.
2
// Channel files must be named *_channel.js.
3
4
const channels = require.context('.', true, /_channel\.js$/)
5
channels.keys().forEach(channels)

+ 17 - 0
app/javascript/packs/application.js

@ -0,0 +1,17 @@
1
// This file is automatically compiled by Webpack, along with any other files
2
// present in this directory. You're encouraged to place your actual application logic in
3
// a relevant structure within app/javascript and only use these pack files to reference
4
// that code so it'll be compiled.
5
6
require("@rails/ujs").start()
7
require("turbolinks").start()
8
require("@rails/activestorage").start()
9
require("channels")
10
11
12
// Uncomment to copy all static images under ../images to the output folder and reference
13
// them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>)
14
// or the `imagePath` JavaScript helper below.
15
//
16
// const images = require.context('../images', true)
17
// const imagePath = (name) => images(name, true)

+ 7 - 0
app/jobs/application_job.rb

@ -0,0 +1,7 @@
1
class ApplicationJob < ActiveJob::Base
2
  # Automatically retry jobs that encountered a deadlock
3
  # retry_on ActiveRecord::Deadlocked
4
5
  # Most jobs are safe to ignore if the underlying records are no longer available
6
  # discard_on ActiveJob::DeserializationError
7
end

+ 4 - 0
app/mailers/application_mailer.rb

@ -0,0 +1,4 @@
1
class ApplicationMailer < ActionMailer::Base
2
  default from: 'from@example.com'
3
  layout 'mailer'
4
end

+ 3 - 0
app/models/application_record.rb

@ -0,0 +1,3 @@
1
class ApplicationRecord < ActiveRecord::Base
2
  self.abstract_class = true
3
end

+ 0 - 0
app/models/concerns/.keep


+ 3 - 0
app/models/subscription.rb

@ -0,0 +1,3 @@
1
class Subscription < ApplicationRecord
2
  has_many :videos
3
end

+ 19 - 0
app/models/video.rb

@ -0,0 +1,19 @@
1
class Video < ApplicationRecord
2
  belongs_to :subscription
3
4
  def path_no_ext
5
    return "/videos/#{self.subscription.url}/#{self.video_id}"
6
  end
7
  
8
  def url_path
9
    return path_no_ext + ".mp4"
10
  end
11
12
  def local_path
13
    return "#{Rails.root}/public#{path_no_ext}.%(ext)s"
14
  end
15
16
  def local_path_ext
17
    return "#{Rails.root}/public#{path_no_ext}.mp4"
18
  end
19
end

+ 20 - 0
app/views/layouts/application.html.erb

@ -0,0 +1,20 @@
1
<!DOCTYPE html>
2
<html>
3
	<head>
4
		<title>YT autodownloader</title>
5
		<%= csrf_meta_tags %>
6
		<%= csp_meta_tag %>
7
8
		<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
9
		<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
10
	</head>
11
12
	<body>
13
		<div class="centertext">
14
			<%= link_to "Home", root_path %>
15
			<%= link_to "Subscriptions", subscriptions_path %><br>
16
			<hr>
17
			<%= yield %>
18
		</div>
19
	</body>
20
</html>

+ 13 - 0
app/views/layouts/mailer.html.erb

@ -0,0 +1,13 @@
1
<!DOCTYPE html>
2
<html>
3
  <head>
4
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5
    <style>
6
      /* Email styles need to be inline */
7
    </style>
8
  </head>
9
10
  <body>
11
    <%= yield %>
12
  </body>
13
</html>

+ 1 - 0
app/views/layouts/mailer.text.erb

@ -0,0 +1 @@
1
<%= yield %>

+ 4 - 0
app/views/subscriptions/index.html.erb

@ -0,0 +1,4 @@
1
<%= link_to "New", new_subscription_path %><br>
2
<% @subs.each do |s| %>
3
<%= s.name %><br>
4
<% end %>

+ 5 - 0
app/views/subscriptions/new.html.erb

@ -0,0 +1,5 @@
1
<%= form_for @sub do |f| %>
2
<%= f.label :url %>
3
<%= f.text_field :url %><br>
4
<%= f.submit %>
5
<% end %>

+ 15 - 0
app/views/videos/index.html.erb

@ -0,0 +1,15 @@
1
<div>
2
	<div style="float: right"><%= @has_next ? (link_to "Next", p: @p + 1) : "" %></div>
3
	<div style="float: left"><%= @has_prev ? (link_to "Prev", p: @p - 1) : "" %></div>
4
	<div style="text-align: center">Page <%= @p %></div>
5
</div>
6
<hr>
7
8
<% @vids.each do |v| %>
9
<div style="background-color:<%= v.is_downloaded ? '#66ff66' : '#dd3333' %>">
10
	<%= link_to v.title, v %><br>
11
	Uploaded: <%= time_ago_in_words(v.published_date) %> ago<br>
12
	By: <%= v.subscription.name %>
13
</div>
14
<hr>
15
<% end %>

+ 7 - 0
app/views/videos/show.html.erb

@ -0,0 +1,7 @@
1
<h1><%= @vid.title %></h1>
2
<video style="width: 100%; margin: 0 auto; display: block" controls>
3
	<source src="<%= @vid.url_path %>" type="video/mp4">
4
</video><br>
5
<p>
6
	<%= simple_format(@vid.description) %>
7
</p>

+ 72 - 0
babel.config.js

@ -0,0 +1,72 @@
1
module.exports = function(api) {
2
  var validEnv = ['development', 'test', 'production']
3
  var currentEnv = api.env()
4
  var isDevelopmentEnv = api.env('development')
5
  var isProductionEnv = api.env('production')
6
  var isTestEnv = api.env('test')
7
8
  if (!validEnv.includes(currentEnv)) {
9
    throw new Error(
10
      'Please specify a valid `NODE_ENV` or ' +
11
        '`BABEL_ENV` environment variables. Valid values are "development", ' +
12
        '"test", and "production". Instead, received: ' +
13
        JSON.stringify(currentEnv) +
14
        '.'
15
    )
16
  }
17
18
  return {
19
    presets: [
20
      isTestEnv && [
21
        '@babel/preset-env',
22
        {
23
          targets: {
24
            node: 'current'
25
          }
26
        }
27
      ],
28
      (isProductionEnv || isDevelopmentEnv) && [
29
        '@babel/preset-env',
30
        {
31
          forceAllTransforms: true,
32
          useBuiltIns: 'entry',
33
          corejs: 3,
34
          modules: false,
35
          exclude: ['transform-typeof-symbol']
36
        }
37
      ]
38
    ].filter(Boolean),
39
    plugins: [
40
      'babel-plugin-macros',
41
      '@babel/plugin-syntax-dynamic-import',
42
      isTestEnv && 'babel-plugin-dynamic-import-node',
43
      '@babel/plugin-transform-destructuring',
44
      [
45
        '@babel/plugin-proposal-class-properties',
46
        {
47
          loose: true
48
        }
49
      ],
50
      [
51
        '@babel/plugin-proposal-object-rest-spread',
52
        {
53
          useBuiltIns: true
54
        }
55
      ],
56
      [
57
        '@babel/plugin-transform-runtime',
58
        {
59
          helpers: false,
60
          regenerator: true,
61
          corejs: false
62
        }
63
      ],
64
      [
65
        '@babel/plugin-transform-regenerator',
66
        {
67
          async: false
68
        }
69
      ]
70
    ].filter(Boolean)
71
  }
72
}

+ 105 - 0
bin/bundle

@ -0,0 +1,105 @@
1
#!/usr/bin/env ruby
2
# frozen_string_literal: true
3
4
#
5
# This file was generated by Bundler.
6
#
7
# The application 'bundle' is installed as part of a gem, and
8
# this file is here to facilitate running it.
9
#
10
11
require "rubygems"
12
13
m = Module.new do
14
    module_function
15
16
  def invoked_as_script?
17
    File.expand_path($0) == File.expand_path(__FILE__)
18
  end
19
20
  def env_var_version
21
    ENV["BUNDLER_VERSION"]
22
  end
23
24
  def cli_arg_version
25
    return unless invoked_as_script? # don't want to hijack other binstubs
26
    return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
27
    bundler_version = nil
28
    update_index = nil
29
    ARGV.each_with_index do |a, i|
30
      if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
31
        bundler_version = a
32
      end
33
      next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
34
      bundler_version = $1 || ">= 0.a"
35
      update_index = i
36
    end
37
    bundler_version
38
  end
39
40
  def gemfile
41
    gemfile = ENV["BUNDLE_GEMFILE"]
42
    return gemfile if gemfile && !gemfile.empty?
43
44
    File.expand_path("../../Gemfile", __FILE__)
45
  end
46
47
  def lockfile
48
    lockfile =
49
      case File.basename(gemfile)
50
      when "gems.rb" then gemfile.sub(/\.rb$/, gemfile)
51
      else "#{gemfile}.lock"
52
      end
53
    File.expand_path(lockfile)
54
  end
55
56
  def lockfile_version
57
    return unless File.file?(lockfile)
58
    lockfile_contents = File.read(lockfile)
59
    return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
60
    Regexp.last_match(1)
61
  end
62
63
  def bundler_version
64
    @bundler_version ||= begin
65
      env_var_version || cli_arg_version ||
66
        lockfile_version || "#{Gem::Requirement.default}.a"
67
    end
68
  end
69
70
  def load_bundler!
71
    ENV["BUNDLE_GEMFILE"] ||= gemfile
72
73
    # must dup string for RG < 1.8 compatibility
74
    activate_bundler(bundler_version.dup)
75
  end
76
77
  def activate_bundler(bundler_version)
78
    if Gem::Version.correct?(bundler_version) && Gem::Version.new(bundler_version).release < Gem::Version.new("2.0")
79
      bundler_version = "< 2"
80
    end
81
    gem_error = activation_error_handling do
82
      gem "bundler", bundler_version
83
    end
84
    return if gem_error.nil?
85
    require_error = activation_error_handling do
86
      require "bundler/version"
87
    end
88
    return if require_error.nil? && Gem::Requirement.new(bundler_version).satisfied_by?(Gem::Version.new(Bundler::VERSION))
89
    warn "Activating bundler (#{bundler_version}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_version}'`"
90
    exit 42
91
  end
92
93
  def activation_error_handling
94
    yield
95
    nil
96
  rescue StandardError, LoadError => e
97
    e
98
  end
99
end
100
101
m.load_bundler!
102
103
if m.invoked_as_script?
104
  load Gem.bin_path("bundler", "bundle")
105
end

+ 9 - 0
bin/rails

@ -0,0 +1,9 @@
1
#!/usr/bin/env ruby
2
begin
3
  load File.expand_path('../spring', __FILE__)
4
rescue LoadError => e
5
  raise unless e.message.include?('spring')
6
end
7
APP_PATH = File.expand_path('../config/application', __dir__)
8
require_relative '../config/boot'
9
require 'rails/commands'

+ 9 - 0
bin/rake

@ -0,0 +1,9 @@
1
#!/usr/bin/env ruby
2
begin
3
  load File.expand_path('../spring', __FILE__)
4
rescue LoadError => e
5
  raise unless e.message.include?('spring')
6
end
7
require_relative '../config/boot'
8
require 'rake'
9
Rake.application.run

+ 36 - 0
bin/setup

@ -0,0 +1,36 @@
1
#!/usr/bin/env ruby
2
require 'fileutils'
3
4
# path to your application root.
5
APP_ROOT = File.expand_path('..', __dir__)
6
7
def system!(*args)
8
  system(*args) || abort("\n== Command #{args} failed ==")
9
end
10
11
FileUtils.chdir APP_ROOT do
12
  # This script is a way to setup or update your development environment automatically.
13
  # This script is idempotent, so that you can run it at anytime and get an expectable outcome.
14
  # Add necessary setup steps to this file.
15
16
  puts '== Installing dependencies =='
17
  system! 'gem install bundler --conservative'
18
  system('bundle check') || system!('bundle install')
19
20
  # Install JavaScript dependencies
21
  # system('bin/yarn')
22
23
  # puts "\n== Copying sample files =="
24
  # unless File.exist?('config/database.yml')
25
  #   FileUtils.cp 'config/database.yml.sample', 'config/database.yml'
26
  # end
27
28
  puts "\n== Preparing database =="
29
  system! 'bin/rails db:prepare'
30
31
  puts "\n== Removing old logs and tempfiles =="
32
  system! 'bin/rails log:clear tmp:clear'
33
34
  puts "\n== Restarting application server =="
35
  system! 'bin/rails restart'
36
end

+ 17 - 0
bin/spring

@ -0,0 +1,17 @@
1
#!/usr/bin/env ruby
2
3
# This file loads Spring without using Bundler, in order to be fast.
4
# It gets overwritten when you run the `spring binstub` command.
5
6
unless defined?(Spring)
7
  require 'rubygems'
8
  require 'bundler'
9
10
  lockfile = Bundler::LockfileParser.new(Bundler.default_lockfile.read)
11
  spring = lockfile.specs.detect { |spec| spec.name == 'spring' }
12
  if spring
13
    Gem.use_paths Gem.dir, Bundler.bundle_path.to_s, *Gem.path
14
    gem 'spring', spring.version
15
    require 'spring/binstub'
16
  end
17
end

+ 18 - 0
bin/webpack

@ -0,0 +1,18 @@
1
#!/usr/bin/env ruby
2
3
ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development"
4
ENV["NODE_ENV"]  ||= "development"
5
6
require "pathname"
7
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
8
  Pathname.new(__FILE__).realpath)
9
10
require "bundler/setup"
11
12
require "webpacker"
13
require "webpacker/webpack_runner"
14
15
APP_ROOT = File.expand_path("..", __dir__)
16
Dir.chdir(APP_ROOT) do
17
  Webpacker::WebpackRunner.run(ARGV)
18
end

+ 18 - 0
bin/webpack-dev-server

@ -0,0 +1,18 @@
1
#!/usr/bin/env ruby
2
3
ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development"
4
ENV["NODE_ENV"]  ||= "development"
5
6
require "pathname"
7
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
8
  Pathname.new(__FILE__).realpath)
9
10
require "bundler/setup"
11
12
require "webpacker"
13
require "webpacker/dev_server_runner"
14
15
APP_ROOT = File.expand_path("..", __dir__)
16
Dir.chdir(APP_ROOT) do
17
  Webpacker::DevServerRunner.run(ARGV)
18
end

+ 11 - 0
bin/yarn

@ -0,0 +1,11 @@
1
#!/usr/bin/env ruby
2
APP_ROOT = File.expand_path('..', __dir__)
3
Dir.chdir(APP_ROOT) do
4
  begin
5
    exec "yarnpkg", *ARGV
6
  rescue Errno::ENOENT
7
    $stderr.puts "Yarn executable was not detected in the system."
8
    $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install"
9
    exit 1
10
  end
11
end

+ 5 - 0
config.ru

@ -0,0 +1,5 @@
1
# This file is used by Rack-based servers to start the application.
2
3
require_relative 'config/environment'
4
5
run Rails.application

+ 19 - 0
config/application.rb

@ -0,0 +1,19 @@
1
require_relative 'boot'
2
3
require 'rails/all'
4
5
# Require the gems listed in Gemfile, including any gems
6
# you've limited to :test, :development, or :production.
7
Bundler.require(*Rails.groups)
8
9
module Ytautodown
10
  class Application < Rails::Application
11
    # Initialize configuration defaults for originally generated Rails version.
12
    config.load_defaults 6.0
13
14
    # Settings in config/environments/* take precedence over those specified here.
15
    # Application configuration can go into files in config/initializers
16
    # -- all .rb files in that directory are automatically loaded after loading
17
    # the framework and any gems in your application.
18
  end
19
end

+ 4 - 0
config/boot.rb

@ -0,0 +1,4 @@
1
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
2
3
require 'bundler/setup' # Set up gems listed in the Gemfile.
4
require 'bootsnap/setup' # Speed up boot time by caching expensive operations.

+ 10 - 0
config/cable.yml

@ -0,0 +1,10 @@
1
development:
2
  adapter: async
3
4
test:
5
  adapter: test
6
7
production:
8
  adapter: redis
9
  url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
10
  channel_prefix: ytautodown_production

+ 1 - 0
config/credentials.yml.enc

@ -0,0 +1 @@
1
++gdj6G4cZY8zgOFDbdRIwbBg/ejZZ0KZsUtvYmK6QJVWBS0GJk9DhayQTuP9y+Y7fzZ1XrWZ8y86rH9e5uPYpP9Ijh6xCZXezx9CnGt/R+84mPp3pM/pws0pbb63f99qy8ZDgqMJ/gVuXa5ewnTKon75cakVqw7QuXQ5evBc3v7sbAyPOpjmtiWWrGb2Xr3yF/u/4i23UNiegqNKQ/9t/7ecNYkcxxlM4XRrjAzcBhbZl1xPdkswPlhg2oGHU7Kq7iBTe8Hz5h1AJFC3lBuE0ycr0Kdm3JIkcxworiZcPXg26jLqRSw8ErH6MYLZc9pHdq7j46yX12XF9HCjxBJhxExNr0SyLuQpj21PPiiJOjJByErU+zu5XPwK09RhP4vYa6Gx/UqnXZHFHUL11fbBsJpdKYggwV3vuZw--uFFzMbGBcPgA3NGN--aAn/QwHjpvZlQSZs1aBmhA==

+ 85 - 0
config/database.yml

@ -0,0 +1,85 @@
1
# PostgreSQL. Versions 9.3 and up are supported.
2
#
3
# Install the pg driver:
4
#   gem install pg
5
# On macOS with Homebrew:
6
#   gem install pg -- --with-pg-config=/usr/local/bin/pg_config
7
# On macOS with MacPorts:
8
#   gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config
9
# On Windows:
10
#   gem install pg
11
#       Choose the win32 build.
12
#       Install PostgreSQL and put its /bin directory on your path.
13
#
14
# Configure Using Gemfile
15
# gem 'pg'
16
#
17
default: &default
18
  adapter: postgresql
19
  encoding: unicode
20
  # For details on connection pooling, see Rails configuration guide
21
  # https://guides.rubyonrails.org/configuring.html#database-pooling
22
  pool: 30 %>
23
24
development:
25
  <<: *default
26
  database: ytautodown_development
27
28
  # The specified database role being used to connect to postgres.
29
  # To create additional roles in postgres see `$ createuser --help`.
30
  # When left blank, postgres will use the default role. This is
31
  # the same name as the operating system user that initialized the database.
32
  #username: ytautodown
33
34
  # The password associated with the postgres role (username).
35
  #password:
36
37
  # Connect on a TCP socket. Omitted by default since the client uses a
38
  # domain socket that doesn't need configuration. Windows does not have
39
  # domain sockets, so uncomment these lines.
40
  #host: localhost
41
42
  # The TCP port the server listens on. Defaults to 5432.
43
  # If your server runs on a different port number, change accordingly.
44
  #port: 5432
45
46
  # Schema search path. The server defaults to $user,public
47
  #schema_search_path: myapp,sharedapp,public
48
49
  # Minimum log levels, in increasing order:
50
  #   debug5, debug4, debug3, debug2, debug1,
51
  #   log, notice, warning, error, fatal, and panic
52
  # Defaults to warning.
53
  #min_messages: notice
54
55
# Warning: The database defined as "test" will be erased and
56
# re-generated from your development database when you run "rake".
57
# Do not set this db to the same as development or production.
58
test:
59
  <<: *default
60
  database: ytautodown_test
61
62
# As with config/credentials.yml, you never want to store sensitive information,
63
# like your database password, in your source code. If your source code is
64
# ever seen by anyone, they now have access to your database.
65
#
66
# Instead, provide the password as a unix environment variable when you boot
67
# the app. Read https://guides.rubyonrails.org/configuring.html#configuring-a-database
68
# for a full rundown on how to provide these environment variables in a
69
# production deployment.
70
#
71
# On Heroku and other platform providers, you may have a full connection URL
72
# available as an environment variable. For example:
73
#
74
#   DATABASE_URL="postgres://myuser:mypass@localhost/somedatabase"
75
#
76
# You can use this database configuration with:
77
#
78
#   production:
79
#     url: <%= ENV['DATABASE_URL'] %>
80
#
81
production:
82
  <<: *default
83
  database: ytautodown_production
84
  username: ytautodown
85
  password: <%= ENV['YTAUTODOWN_DATABASE_PASSWORD'] %>

+ 5 - 0
config/environment.rb

@ -0,0 +1,5 @@
1
# Load the Rails application.
2
require_relative 'application'
3
4
# Initialize the Rails application.
5
Rails.application.initialize!

+ 62 - 0
config/environments/development.rb

@ -0,0 +1,62 @@
1
Rails.application.configure do
2
  # Settings specified here will take precedence over those in config/application.rb.
3
4
  # In the development environment your application's code is reloaded on
5
  # every request. This slows down response time but is perfect for development
6
  # since you don't have to restart the web server when you make code changes.
7
  config.cache_classes = false
8
9
  # Do not eager load code on boot.
10
  config.eager_load = false
11
12
  # Show full error reports.
13
  config.consider_all_requests_local = true
14
15
  # Enable/disable caching. By default caching is disabled.
16
  # Run rails dev:cache to toggle caching.
17
  if Rails.root.join('tmp', 'caching-dev.txt').exist?
18
    config.action_controller.perform_caching = true
19
    config.action_controller.enable_fragment_cache_logging = true
20
21
    config.cache_store = :memory_store
22
    config.public_file_server.headers = {
23
      'Cache-Control' => "public, max-age=#{2.days.to_i}"
24
    }
25
  else
26
    config.action_controller.perform_caching = false
27
28
    config.cache_store = :null_store
29
  end
30
31
  # Store uploaded files on the local file system (see config/storage.yml for options).
32
  config.active_storage.service = :local
33
34
  # Don't care if the mailer can't send.
35
  config.action_mailer.raise_delivery_errors = false
36
37
  config.action_mailer.perform_caching = false
38
39
  # Print deprecation notices to the Rails logger.
40
  config.active_support.deprecation = :log
41
42
  # Raise an error on page load if there are pending migrations.
43
  config.active_record.migration_error = :page_load
44
45
  # Highlight code that triggered database queries in logs.
46
  config.active_record.verbose_query_logs = true
47
48
  # Debug mode disables concatenation and preprocessing of assets.
49
  # This option may cause significant delays in view rendering with a large
50
  # number of complex assets.
51
  config.assets.debug = true
52
53
  # Suppress logger output for asset requests.
54
  config.assets.quiet = true
55
56
  # Raises error for missing translations.
57
  # config.action_view.raise_on_missing_translations = true
58
59
  # Use an evented file watcher to asynchronously detect changes in source code,
60
  # routes, locales, etc. This feature depends on the listen gem.
61
  config.file_watcher = ActiveSupport::EventedFileUpdateChecker
62
end

+ 112 - 0
config/environments/production.rb

@ -0,0 +1,112 @@
1
Rails.application.configure do
2
  # Settings specified here will take precedence over those in config/application.rb.
3
4
  # Code is not reloaded between requests.
5
  config.cache_classes = true
6
7
  # Eager load code on boot. This eager loads most of Rails and
8
  # your application in memory, allowing both threaded web servers
9
  # and those relying on copy on write to perform better.
10
  # Rake tasks automatically ignore this option for performance.
11
  config.eager_load = true
12
13
  # Full error reports are disabled and caching is turned on.
14
  config.consider_all_requests_local       = false
15
  config.action_controller.perform_caching = true
16
17
  # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"]
18
  # or in config/master.key. This key is used to decrypt credentials (and other encrypted files).
19
  # config.require_master_key = true
20
21
  # Disable serving static files from the `/public` folder by default since
22
  # Apache or NGINX already handles this.
23
  config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
24
25
  # Compress CSS using a preprocessor.
26
  # config.assets.css_compressor = :sass
27
28
  # Do not fallback to assets pipeline if a precompiled asset is missed.
29
  config.assets.compile = false
30
31
  # Enable serving of images, stylesheets, and JavaScripts from an asset server.
32
  # config.action_controller.asset_host = 'http://assets.example.com'
33
34
  # Specifies the header that your server uses for sending files.
35
  # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
36
  # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
37
38
  # Store uploaded files on the local file system (see config/storage.yml for options).
39
  config.active_storage.service = :local
40
41
  # Mount Action Cable outside main process or domain.
42
  # config.action_cable.mount_path = nil
43
  # config.action_cable.url = 'wss://example.com/cable'
44
  # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ]
45
46
  # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
47
  # config.force_ssl = true
48
49
  # Use the lowest log level to ensure availability of diagnostic information
50
  # when problems arise.
51
  config.log_level = :debug
52
53
  # Prepend all log lines with the following tags.
54
  config.log_tags = [ :request_id ]
55
56
  # Use a different cache store in production.
57
  # config.cache_store = :mem_cache_store
58
59
  # Use a real queuing backend for Active Job (and separate queues per environment).
60
  # config.active_job.queue_adapter     = :resque
61
  # config.active_job.queue_name_prefix = "ytautodown_production"
62
63
  config.action_mailer.perform_caching = false
64
65
  # Ignore bad email addresses and do not raise email delivery errors.
66
  # Set this to true and configure the email server for immediate delivery to raise delivery errors.
67
  # config.action_mailer.raise_delivery_errors = false
68
69
  # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
70
  # the I18n.default_locale when a translation cannot be found).
71
  config.i18n.fallbacks = true
72
73
  # Send deprecation notices to registered listeners.
74
  config.active_support.deprecation = :notify
75
76
  # Use default logging formatter so that PID and timestamp are not suppressed.
77
  config.log_formatter = ::Logger::Formatter.new
78
79
  # Use a different logger for distributed setups.
80
  # require 'syslog/logger'
81
  # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name')
82
83
  if ENV["RAILS_LOG_TO_STDOUT"].present?
84
    logger           = ActiveSupport::Logger.new(STDOUT)
85
    logger.formatter = config.log_formatter
86
    config.logger    = ActiveSupport::TaggedLogging.new(logger)
87
  end
88
89
  # Do not dump schema after migrations.
90
  config.active_record.dump_schema_after_migration = false
91
92
  # Inserts middleware to perform automatic connection switching.
93
  # The `database_selector` hash is used to pass options to the DatabaseSelector
94
  # middleware. The `delay` is used to determine how long to wait after a write
95
  # to send a subsequent read to the primary.
96
  #
97
  # The `database_resolver` class is used by the middleware to determine which
98
  # database is appropriate to use based on the time delay.
99
  #
100
  # The `database_resolver_context` class is used by the middleware to set
101
  # timestamps for the last write to the primary. The resolver uses the context
102
  # class timestamps to determine how long to wait before reading from the
103
  # replica.
104
  #
105
  # By default Rails will store a last write timestamp in the session. The
106
  # DatabaseSelector middleware is designed as such you can define your own
107
  # strategy for connection switching and pass that into the middleware through
108
  # these configuration options.
109
  # config.active_record.database_selector = { delay: 2.seconds }
110
  # config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver
111
  # config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session
112
end

+ 48 - 0
config/environments/test.rb

@ -0,0 +1,48 @@
1
# The test environment is used exclusively to run your application's
2
# test suite. You never need to work with it otherwise. Remember that
3
# your test database is "scratch space" for the test suite and is wiped
4
# and recreated between test runs. Don't rely on the data there!
5
6
Rails.application.configure do
7
  # Settings specified here will take precedence over those in config/application.rb.
8
9
  config.cache_classes = false
10
11
  # Do not eager load code on boot. This avoids loading your whole application
12
  # just for the purpose of running a single test. If you are using a tool that
13
  # preloads Rails for running tests, you may have to set it to true.
14
  config.eager_load = false
15
16
  # Configure public file server for tests with Cache-Control for performance.
17
  config.public_file_server.enabled = true
18
  config.public_file_server.headers = {
19
    'Cache-Control' => "public, max-age=#{1.hour.to_i}"
20
  }
21
22
  # Show full error reports and disable caching.
23
  config.consider_all_requests_local       = true
24
  config.action_controller.perform_caching = false
25
  config.cache_store = :null_store
26
27
  # Raise exceptions instead of rendering exception templates.
28
  config.action_dispatch.show_exceptions = false
29
30
  # Disable request forgery protection in test environment.
31
  config.action_controller.allow_forgery_protection = false
32
33
  # Store uploaded files on the local file system in a temporary directory.
34
  config.active_storage.service = :test
35
36
  config.action_mailer.perform_caching = false
37
38
  # Tell Action Mailer not to deliver emails to the real world.
39
  # The :test delivery method accumulates sent emails in the
40
  # ActionMailer::Base.deliveries array.
41
  config.action_mailer.delivery_method = :test
42
43
  # Print deprecation notices to the stderr.
44
  config.active_support.deprecation = :stderr
45
46
  # Raises error for missing translations.
47
  # config.action_view.raise_on_missing_translations = true
48
end

+ 8 - 0
config/initializers/application_controller_renderer.rb

@ -0,0 +1,8 @@
1
# Be sure to restart your server when you modify this file.
2
3
# ActiveSupport::Reloader.to_prepare do
4
#   ApplicationController.renderer.defaults.merge!(
5
#     http_host: 'example.org',
6
#     https: false
7
#   )
8
# end

+ 14 - 0
config/initializers/assets.rb

@ -0,0 +1,14 @@
1
# Be sure to restart your server when you modify this file.
2
3
# Version of your assets, change this if you want to expire all your assets.
4
Rails.application.config.assets.version = '1.0'
5
6
# Add additional assets to the asset load path.
7
# Rails.application.config.assets.paths << Emoji.images_path
8
# Add Yarn node_modules folder to the asset load path.
9
Rails.application.config.assets.paths << Rails.root.join('node_modules')
10
11
# Precompile additional assets.
12
# application.js, application.css, and all non-JS/CSS in the app/assets
13
# folder are already added.
14
# Rails.application.config.assets.precompile += %w( admin.js admin.css )

+ 7 - 0
config/initializers/backtrace_silencers.rb

@ -0,0 +1,7 @@
1
# Be sure to restart your server when you modify this file.
2
3
# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
4
# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
5
6
# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
7
# Rails.backtrace_cleaner.remove_silencers!

+ 30 - 0
config/initializers/content_security_policy.rb

@ -0,0 +1,30 @@
1
# Be sure to restart your server when you modify this file.
2
3
# Define an application-wide content security policy
4
# For further information see the following documentation
5
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy
6
7
# Rails.application.config.content_security_policy do |policy|
8
#   policy.default_src :self, :https
9
#   policy.font_src    :self, :https, :data
10
#   policy.img_src     :self, :https, :data
11
#   policy.object_src  :none
12
#   policy.script_src  :self, :https
13
#   policy.style_src   :self, :https
14
#   # If you are using webpack-dev-server then specify webpack-dev-server host
15
#   policy.connect_src :self, :https, "http://localhost:3035", "ws://localhost:3035" if Rails.env.development?
16
17
#   # Specify URI for violation reports
18
#   # policy.report_uri "/csp-violation-report-endpoint"
19
# end
20
21
# If you are using UJS then enable automatic nonce generation
22
# Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) }
23
24
# Set the nonce only to specific directives
25
# Rails.application.config.content_security_policy_nonce_directives = %w(script-src)
26
27
# Report CSP violations to a specified URI
28
# For further information see the following documentation:
29
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only
30
# Rails.application.config.content_security_policy_report_only = true

+ 5 - 0
config/initializers/cookies_serializer.rb

@ -0,0 +1,5 @@
1
# Be sure to restart your server when you modify this file.
2
3
# Specify a serializer for the signed and encrypted cookie jars.
4
# Valid options are :json, :marshal, and :hybrid.
5
Rails.application.config.action_dispatch.cookies_serializer = :json

+ 4 - 0
config/initializers/filter_parameter_logging.rb

@ -0,0 +1,4 @@
1
# Be sure to restart your server when you modify this file.
2
3
# Configure sensitive parameters which will be filtered from the log file.
4
Rails.application.config.filter_parameters += [:password]

+ 16 - 0
config/initializers/inflections.rb

@ -0,0 +1,16 @@
1
# Be sure to restart your server when you modify this file.
2
3
# Add new inflection rules using the following format. Inflections
4
# are locale specific, and you may define rules for as many different
5
# locales as you wish. All of these examples are active by default:
6
# ActiveSupport::Inflector.inflections(:en) do |inflect|
7
#   inflect.plural /^(ox)$/i, '\1en'
8
#   inflect.singular /^(ox)en/i, '\1'
9
#   inflect.irregular 'person', 'people'
10
#   inflect.uncountable %w( fish sheep )
11
# end
12
13
# These inflection rules are supported but not enabled by default:
14
# ActiveSupport::Inflector.inflections(:en) do |inflect|
15
#   inflect.acronym 'RESTful'
16
# end

+ 5 - 0
config/initializers/mime_types.rb

@ -0,0 +1,5 @@
1
# Be sure to restart your server when you modify this file.
2
3
# Add new mime types for use in respond_to blocks:
4
# Mime::Type.register "text/richtext", :rtf
5
Rack::Mime::MIME_TYPES[".webm"]="video/webm"

+ 19 - 0
config/initializers/scheduler.rb

@ -0,0 +1,19 @@
1
require 'rufus-scheduler'
2
require 'youtube'
3
4
return if defined?(Rails::Console) || Rails.env.test? || File.split($0).last == 'rake'
5
6
s = Rufus::Scheduler.singleton
7
8
s.every '5m' do
9
  Youtube.update_from_subs
10
end
11
12
busy = false
13
s.every '10m' do
14
  unless busy
15
    busy = true
16
    Youtube.scrape_videos
17
    busy = false
18
  end
19
end

+ 14 - 0
config/initializers/wrap_parameters.rb

@ -0,0 +1,14 @@
1
# Be sure to restart your server when you modify this file.
2
3
# This file contains settings for ActionController::ParamsWrapper which
4
# is enabled by default.
5
6
# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
7
ActiveSupport.on_load(:action_controller) do
8
  wrap_parameters format: [:json]
9
end
10
11
# To enable root element in JSON for ActiveRecord objects.
12
# ActiveSupport.on_load(:active_record) do
13
#   self.include_root_in_json = true
14
# end

+ 33 - 0
config/locales/en.yml

@ -0,0 +1,33 @@
1
# Files in the config/locales directory are used for internationalization
2
# and are automatically loaded by Rails. If you want to use locales other
3
# than English, add the necessary files in this directory.
4
#
5
# To use the locales, use `I18n.t`:
6
#
7
#     I18n.t 'hello'
8
#
9
# In views, this is aliased to just `t`:
10
#
11
#     <%= t('hello') %>
12
#
13
# To use a different locale, set it with `I18n.locale`:
14
#
15
#     I18n.locale = :es
16
#
17
# This would use the information in config/locales/es.yml.
18
#
19
# The following keys must be escaped otherwise they will not be retrieved by
20
# the default I18n backend:
21
#
22
# true, false, on, off, yes, no
23
#
24
# Instead, surround them with single quotes.
25
#
26
# en:
27
#   'true': 'foo'
28
#
29
# To learn more, please read the Rails Internationalization guide
30
# available at https://guides.rubyonrails.org/i18n.html.
31
32
en:
33
  hello: "Hello world"

+ 38 - 0
config/puma.rb

@ -0,0 +1,38 @@
1
# Puma can serve each request in a thread from an internal thread pool.
2
# The `threads` method setting takes two numbers: a minimum and maximum.
3
# Any libraries that use thread pools should be configured to match
4
# the maximum value specified for Puma. Default is set to 5 threads for minimum
5
# and maximum; this matches the default thread size of Active Record.
6
#
7
max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
8
min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count }
9
threads min_threads_count, max_threads_count
10
11
# Specifies the `port` that Puma will listen on to receive requests; default is 3000.
12
#
13
port        ENV.fetch("PORT") { 3000 }
14
15
# Specifies the `environment` that Puma will run in.
16
#
17
environment ENV.fetch("RAILS_ENV") { "development" }
18
19
# Specifies the `pidfile` that Puma will use.
20
pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }
21
22
# Specifies the number of `workers` to boot in clustered mode.
23
# Workers are forked web server processes. If using threads and workers together
24
# the concurrency of the application would be max `threads` * `workers`.
25
# Workers do not work on JRuby or Windows (both of which do not support
26
# processes).
27
#
28
# workers ENV.fetch("WEB_CONCURRENCY") { 2 }
29
30
# Use the `preload_app!` method when specifying a `workers` number.
31
# This directive tells Puma to first boot the application and load code
32
# before forking the application. This takes advantage of Copy On Write
33
# process behavior so workers use less memory.
34
#
35
# preload_app!
36
37
# Allow puma to be restarted by `rails restart` command.
38
plugin :tmp_restart

+ 5 - 0
config/routes.rb

@ -0,0 +1,5 @@
1
Rails.application.routes.draw do
2
  root "videos#index"
3
  resources :subscriptions
4
  resources :videos
5
end

+ 6 - 0
config/spring.rb

@ -0,0 +1,6 @@
1
Spring.watch(
2
  ".ruby-version",
3
  ".rbenv-vars",
4
  "tmp/restart.txt",
5
  "tmp/caching-dev.txt"
6
)

+ 34 - 0
config/storage.yml

@ -0,0 +1,34 @@
1
test:
2
  service: Disk
3
  root: <%= Rails.root.join("tmp/storage") %>
4
5
local:
6
  service: Disk
7
  root: <%= Rails.root.join("storage") %>
8
9
# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
10
# amazon:
11
#   service: S3
12
#   access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
13
#   secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
14
#   region: us-east-1
15
#   bucket: your_own_bucket
16
17
# Remember not to checkin your GCS keyfile to a repository
18
# google:
19
#   service: GCS
20
#   project: your_project
21
#   credentials: <%= Rails.root.join("path/to/gcs.keyfile") %>
22
#   bucket: your_own_bucket
23
24
# Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key)
25
# microsoft:
26
#   service: AzureStorage
27
#   storage_account_name: your_account_name
28
#   storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %>
29
#   container: your_container_name
30
31
# mirror:
32
#   service: Mirror
33
#   primary: local
34
#   mirrors: [ amazon, google, microsoft ]

+ 5 - 0
config/webpack/development.js

@ -0,0 +1,5 @@
1
process.env.NODE_ENV = process.env.NODE_ENV || 'development'
2
3
const environment = require('./environment')
4
5
module.exports = environment.toWebpackConfig()

+ 3 - 0
config/webpack/environment.js

@ -0,0 +1,3 @@
1
const { environment } = require('@rails/webpacker')
2
3
module.exports = environment

+ 5 - 0
config/webpack/production.js

@ -0,0 +1,5 @@
1
process.env.NODE_ENV = process.env.NODE_ENV || 'production'
2
3
const environment = require('./environment')
4
5
module.exports = environment.toWebpackConfig()

+ 5 - 0
config/webpack/test.js

@ -0,0 +1,5 @@
1
process.env.NODE_ENV = process.env.NODE_ENV || 'development'
2
3
const environment = require('./environment')
4
5
module.exports = environment.toWebpackConfig()

+ 96 - 0
config/webpacker.yml

@ -0,0 +1,96 @@
1
# Note: You must restart bin/webpack-dev-server for changes to take effect
2
3
default: &default
4
  source_path: app/javascript
5
  source_entry_path: packs
6
  public_root_path: public
7
  public_output_path: packs
8
  cache_path: tmp/cache/webpacker
9
  check_yarn_integrity: false
10
  webpack_compile_output: true
11
12
  # Additional paths webpack should lookup modules
13
  # ['app/assets', 'engine/foo/app/assets']
14
  resolved_paths: []
15
16
  # Reload manifest.json on all requests so we reload latest compiled packs
17
  cache_manifest: false
18
19
  # Extract and emit a css file
20
  extract_css: false
21
22
  static_assets_extensions:
23
    - .jpg
24
    - .jpeg
25
    - .png
26
    - .gif
27
    - .tiff
28
    - .ico
29
    - .svg
30
    - .eot
31
    - .otf
32
    - .ttf
33
    - .woff
34
    - .woff2
35
36
  extensions:
37
    - .mjs
38
    - .js
39
    - .sass
40
    - .scss
41
    - .css
42
    - .module.sass
43
    - .module.scss
44
    - .module.css
45
    - .png
46
    - .svg
47
    - .gif
48
    - .jpeg
49
    - .jpg
50
51
development:
52
  <<: *default
53
  compile: true
54
55
  # Verifies that correct packages and versions are installed by inspecting package.json, yarn.lock, and node_modules
56
  check_yarn_integrity: true
57
58
  # Reference: https://webpack.js.org/configuration/dev-server/
59
  dev_server:
60
    https: false
61
    host: localhost
62
    port: 3035
63
    public: localhost:3035
64
    hmr: false
65
    # Inline should be set to true if using HMR
66
    inline: true
67
    overlay: true
68
    compress: true
69
    disable_host_check: true
70
    use_local_ip: false
71
    quiet: false
72
    pretty: false
73
    headers:
74
      'Access-Control-Allow-Origin': '*'
75
    watch_options:
76
      ignored: '**/node_modules/**'
77
78
79
test:
80
  <<: *default
81
  compile: true
82
83
  # Compile test packs to a separate directory
84
  public_output_path: packs-test
85
86
production:
87
  <<: *default
88
89
  # Production depends on precompilation of packs prior to booting for performance.
90
  compile: false
91
92
  # Extract and emit a css file
93
  extract_css: true
94
95
  # Cache manifest.json for performance
96
  cache_manifest: true

+ 8 - 0
db/migrate/20191210031133_create_subscriptions.rb

@ -0,0 +1,8 @@
1
class CreateSubscriptions < ActiveRecord::Migration[6.0]
2
  def change
3
    create_table :subscriptions do |t|
4
      t.string :name
5
      t.string :url
6
    end
7
  end
8
end

+ 14 - 0
db/migrate/20191210122329_create_videos.rb

@ -0,0 +1,14 @@
1
class CreateVideos < ActiveRecord::Migration[6.0]
2
  def change
3
    create_table :videos do |t|
4
      t.string :title
5
      t.string :description
6
      t.references :subscription, null: false, foreign_key: true
7
      t.string :video_id
8
      t.string :video_url
9
      t.datetime :published_date
10
      t.boolean :is_downloaded
11
      t.string :thumbnail_url
12
    end
13
  end
14
end

+ 36 - 0
db/schema.rb

@ -0,0 +1,36 @@
1
# This file is auto-generated from the current state of the database. Instead
2
# of editing this file, please use the migrations feature of Active Record to
3
# incrementally modify your database, and then regenerate this schema definition.
4
#
5
# This file is the source Rails uses to define your schema when running `rails
6
# db:schema:load`. When creating a new database, `rails db:schema:load` tends to
7
# be faster and is potentially less error prone than running all of your
8
# migrations from scratch. Old migrations may fail to apply correctly if those
9
# migrations use external dependencies or application code.
10
#
11
# It's strongly recommended that you check this file into your version control system.
12
13
ActiveRecord::Schema.define(version: 2019_12_10_122329) do
14
15
  # These are extensions that must be enabled in order to support this database
16
  enable_extension "plpgsql"
17
18
  create_table "subscriptions", force: :cascade do |t|
19
    t.string "name"
20
    t.string "url"
21
  end
22
23
  create_table "videos", force: :cascade do |t|
24
    t.string "title"
25
    t.string "description"
26
    t.bigint "subscription_id", null: false
27
    t.string "video_id"
28
    t.string "video_url"
29
    t.datetime "published_date"
30
    t.boolean "is_downloaded"
31
    t.string "thumbnail_url"
32
    t.index ["subscription_id"], name: "index_videos_on_subscription_id"
33
  end
34
35
  add_foreign_key "videos", "subscriptions"
36
end

+ 7 - 0
db/seeds.rb

@ -0,0 +1,7 @@
1
# This file should contain all the record creation needed to seed the database with its default values.
2
# The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup).
3
#
4
# Examples:
5
#
6
#   movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }])
7
#   Character.create(name: 'Luke', movie: movies.first)

+ 0 - 0
lib/assets/.keep


+ 0 - 0
lib/tasks/.keep


+ 81 - 0
lib/youtube.rb

@ -0,0 +1,81 @@
1
class Youtube
2
  def self.update_from_subs()
3
    Subscription.all.each do |s|
4
      begin
5
        h = self.get_channel_videos(s.url)
6
        if s.name.nil?
7
          s.name = h["title"]
8
          s.save
9
        end
10
        
11
        h["entry"].each do |v|
12
          if Video.find_by(video_url: v["link"]["href"]).nil?
13
            a = s.videos.create(title: v["title"],
14
                                description: v["group"]["description"],
15
                                video_id: v["videoId"],
16
                                video_url: v["link"]["href"],
17
                                published_date: v["published"].to_datetime,
18
                                is_downloaded: false,
19
                                thumbnail_url: v["group"]["thumbnail"]["url"])
20
            a.save
21
          end
22
        end
23
      rescue
24
        s.name = "BROKEN!"
25
        s.save
26
      end
27
    end
28
  end
29
  
30
  def self.get_channel_videos(s)
31
    url = "https://www.youtube.com/feeds/videos.xml?channel_id=#{s}"
32
    xml = Net::HTTP.get(URI.parse(url))
33
    h = Hash.from_xml(xml)
34
    return h["feed"]
35
  end
36
37
  def self.scrape_videos
38
    Video.where(is_downloaded: false).order(published_date: :desc).each do |v|
39
      v.is_downloaded = nil #In progress
40
      v.save
41
      cmd = "youtube-dl -ciw -o \"#{v.local_path}\" #{v.video_url}"
42
      filename = `#{cmd} --get-filename`.delete("\n").delete("\r")
43
      puts `#{cmd}`
44
      if !File.exist?(filename)
45
        filename = filename.rpartition('.')[0] + ".mkv"
46
      end
47
      
48
      if File.exist?(filename)
49
        puts `ffmpeg -n -i #{filename} #{v.local_path_ext} && rm #{filename}`
50
      else
51
        puts "#{filename} DNE!"
52
      end
53
      
54
      if File.exist?(v.local_path_ext)
55
      #Success
56
        v.is_downloaded = true
57
        v.save
58
      else
59
        v.is_downloaded = false
60
        v.save
61
        puts "ERROR: Was unable to scrape video #{v.id}"
62
      end
63
    end
64
  end
65
66
  def self.remove_broken_vids
67
    vids = Video.where(is_downloaded: true)
68
    vids.each do |v|
69
      if !File.exist?(v.local_path_ext)
70
        v.is_downloaded = false
71
        v.save
72
      end
73
    end
74
  end
75
  
76
  #def self.download_channel(s)
77
  #  channel = "https://www.youtube.com/user/#{s}"
78
  #  cmd = "/usr/bin/youtube-dl -f best -ciw -o \"#{Rails.root.to_s}/public/videos/#{s}/%(title)s.%(ext)s\" -v #{channel}"
79
  #  `#{cmd}`
80
  #end
81
end

+ 0 - 0
log/.keep


+ 41 - 0
other/scraper.py

@ -0,0 +1,41 @@
1
download_location = "/media/storage/yaas/public/videos/"
2
3
import psycopg2
4
import youtube_dl
5
import subprocess
6
from pathlib import Path
7
import os
8
9
conn = psycopg2.connect(database = "yaas_development",
10
						 user = "stephen",
11
						 host = "127.0.0.1")
12
13
cur = conn.cursor()
14
15
def download_vid(id, url):