├── .discourse-compatibility ├── .github └── workflows │ └── discourse-plugin.yml ├── .gitignore ├── .npmrc ├── .prettierrc.cjs ├── .rubocop.yml ├── .streerc ├── .template-lintrc.cjs ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── README.md ├── app ├── controllers │ └── discourse_rss_polling │ │ └── feed_settings_controller.rb ├── jobs │ └── jobs │ │ └── discourse_rss_polling │ │ ├── fix_topic_embed_authors.rb │ │ ├── poll_all_feeds.rb │ │ └── poll_feed.rb ├── models │ └── discourse_rss_polling │ │ ├── feed_item.rb │ │ ├── feed_setting.rb │ │ └── rss_feed.rb └── services │ └── discourse_rss_polling │ └── feed_setting_finder.rb ├── assets ├── javascripts │ ├── admin │ │ └── models │ │ │ └── rss-polling-feed-settings.js │ └── discourse │ │ ├── controllers │ │ └── admin-plugins-rss-polling.js │ │ ├── routes │ │ └── admin-plugins-rss-polling.js │ │ ├── rss-polling-route-map.js │ │ └── templates │ │ └── admin │ │ └── plugins-rss-polling.gjs └── stylesheets │ └── rss-polling.scss ├── config ├── locales │ ├── client.ar.yml │ ├── client.be.yml │ ├── client.bg.yml │ ├── client.bs_BA.yml │ ├── client.ca.yml │ ├── client.cs.yml │ ├── client.da.yml │ ├── client.de.yml │ ├── client.el.yml │ ├── client.en.yml │ ├── client.en_GB.yml │ ├── client.es.yml │ ├── client.et.yml │ ├── client.fa_IR.yml │ ├── client.fi.yml │ ├── client.fr.yml │ ├── client.gl.yml │ ├── client.he.yml │ ├── client.hr.yml │ ├── client.hu.yml │ ├── client.hy.yml │ ├── client.id.yml │ ├── client.it.yml │ ├── client.ja.yml │ ├── client.ko.yml │ ├── client.lt.yml │ ├── client.lv.yml │ ├── client.nb_NO.yml │ ├── client.nl.yml │ ├── client.pl_PL.yml │ ├── client.pt.yml │ ├── client.pt_BR.yml │ ├── client.ro.yml │ ├── client.ru.yml │ ├── client.sk.yml │ ├── client.sl.yml │ ├── client.sq.yml │ ├── client.sr.yml │ ├── client.sv.yml │ ├── client.sw.yml │ ├── client.te.yml │ ├── client.th.yml │ ├── client.tr_TR.yml │ ├── client.ug.yml │ ├── client.uk.yml │ ├── client.ur.yml │ ├── client.vi.yml │ ├── client.zh_CN.yml │ ├── client.zh_TW.yml │ ├── server.ar.yml │ ├── server.be.yml │ ├── server.bg.yml │ ├── server.bs_BA.yml │ ├── server.ca.yml │ ├── server.cs.yml │ ├── server.da.yml │ ├── server.de.yml │ ├── server.el.yml │ ├── server.en.yml │ ├── server.en_GB.yml │ ├── server.es.yml │ ├── server.et.yml │ ├── server.fa_IR.yml │ ├── server.fi.yml │ ├── server.fr.yml │ ├── server.gl.yml │ ├── server.he.yml │ ├── server.hr.yml │ ├── server.hu.yml │ ├── server.hy.yml │ ├── server.id.yml │ ├── server.it.yml │ ├── server.ja.yml │ ├── server.ko.yml │ ├── server.lt.yml │ ├── server.lv.yml │ ├── server.nb_NO.yml │ ├── server.nl.yml │ ├── server.pl_PL.yml │ ├── server.pt.yml │ ├── server.pt_BR.yml │ ├── server.ro.yml │ ├── server.ru.yml │ ├── server.sk.yml │ ├── server.sl.yml │ ├── server.sq.yml │ ├── server.sr.yml │ ├── server.sv.yml │ ├── server.sw.yml │ ├── server.te.yml │ ├── server.th.yml │ ├── server.tr_TR.yml │ ├── server.ug.yml │ ├── server.uk.yml │ ├── server.ur.yml │ ├── server.vi.yml │ ├── server.zh_CN.yml │ └── server.zh_TW.yml ├── routes.rb └── settings.yml ├── db └── migrate │ ├── 20180828095129_push_fix_topic_embed_authors_job.rb │ ├── 20230318130154_create_discourse_rss_polling_rss_feeds.rb │ └── 20230319115620_move_rss_yaml_to_db.rb ├── eslint.config.mjs ├── lib └── discourse_rss_polling │ └── engine.rb ├── package.json ├── plugin.rb ├── pnpm-lock.yaml ├── spec ├── fixtures │ └── files │ │ ├── escaped_html.atom │ │ ├── mastodon.rss │ │ ├── multiple_categories.atom │ │ ├── no_content_only_summary.atom │ │ ├── youtube_channel.xml │ │ └── youtube_playlist.xml ├── jobs │ ├── fix_topic_embed_authors_spec.rb │ ├── poll_all_feeds_spec.rb │ └── poll_feed_spec.rb ├── models │ ├── feed_item_spec.rb │ └── feed_setting_spec.rb ├── plugin_helper.rb ├── requests │ └── feed_settings_controller_spec.rb ├── services │ └── feed_setting_finder_spec.rb └── system │ └── core_features_spec.rb ├── stylelint.config.mjs └── translator.yml /.discourse-compatibility: -------------------------------------------------------------------------------- 1 | < 3.5.0.beta5-dev: 90a0179846da8c56665573daa6e60604182ec797 2 | < 3.5.0.beta1-dev: 69bbeae3a249dcd51dd8bcd04d459e6e6d70d5e9 3 | < 3.4.0.beta2-dev: 12d39da14b306c0fa53d463166e91c55845ef6a5 4 | < 3.4.0.beta1-dev: ae42e81fb2dbbdda96811161640d74cdce7fc26e 5 | < 3.3.0.beta1-dev: 14c6b2e36d1a3d534677463723ca5666eac2dd14 6 | 3.1.999: 719d93c9b6ea1f6c3b1ee3d84db440973142fcc7 7 | 2.8.0.beta3: 1e85fa1e5f20cbee1d51990b2eb00106f367a57b 8 | 2.7.0.beta3: 45b174a3e5fb3bea07fa613412da4d3c9c2858bf 9 | -------------------------------------------------------------------------------- /.github/workflows/discourse-plugin.yml: -------------------------------------------------------------------------------- 1 | name: Discourse Plugin 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | 9 | jobs: 10 | ci: 11 | uses: discourse/.github/.github/workflows/discourse-plugin.yml@v1 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | /gems 3 | /auto_generated 4 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict = true 2 | auto-install-peers = false 3 | -------------------------------------------------------------------------------- /.prettierrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = require("@discourse/lint-configs/prettier"); 2 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | inherit_gem: 2 | rubocop-discourse: stree-compat.yml 3 | -------------------------------------------------------------------------------- /.streerc: -------------------------------------------------------------------------------- 1 | --print-width=100 2 | --plugins=plugin/trailing_comma 3 | -------------------------------------------------------------------------------- /.template-lintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = require("@discourse/lint-configs/template-lint"); 2 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source "https://rubygems.org" 4 | 5 | group :development do 6 | gem "rubocop-discourse" 7 | gem "syntax_tree" 8 | end 9 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | activesupport (8.0.2) 5 | base64 6 | benchmark (>= 0.3) 7 | bigdecimal 8 | concurrent-ruby (~> 1.0, >= 1.3.1) 9 | connection_pool (>= 2.2.5) 10 | drb 11 | i18n (>= 1.6, < 2) 12 | logger (>= 1.4.2) 13 | minitest (>= 5.1) 14 | securerandom (>= 0.3) 15 | tzinfo (~> 2.0, >= 2.0.5) 16 | uri (>= 0.13.1) 17 | ast (2.4.3) 18 | base64 (0.3.0) 19 | benchmark (0.4.1) 20 | bigdecimal (3.2.0) 21 | concurrent-ruby (1.3.5) 22 | connection_pool (2.5.3) 23 | drb (2.2.3) 24 | i18n (1.14.7) 25 | concurrent-ruby (~> 1.0) 26 | json (2.12.2) 27 | language_server-protocol (3.17.0.5) 28 | lint_roller (1.1.0) 29 | logger (1.7.0) 30 | minitest (5.25.5) 31 | parallel (1.27.0) 32 | parser (3.3.8.0) 33 | ast (~> 2.4.1) 34 | racc 35 | prettier_print (1.2.1) 36 | prism (1.4.0) 37 | racc (1.8.1) 38 | rack (3.1.15) 39 | rainbow (3.1.1) 40 | regexp_parser (2.10.0) 41 | rubocop (1.75.8) 42 | json (~> 2.3) 43 | language_server-protocol (~> 3.17.0.2) 44 | lint_roller (~> 1.1.0) 45 | parallel (~> 1.10) 46 | parser (>= 3.3.0.2) 47 | rainbow (>= 2.2.2, < 4.0) 48 | regexp_parser (>= 2.9.3, < 3.0) 49 | rubocop-ast (>= 1.44.0, < 2.0) 50 | ruby-progressbar (~> 1.7) 51 | unicode-display_width (>= 2.4.0, < 4.0) 52 | rubocop-ast (1.44.1) 53 | parser (>= 3.3.7.2) 54 | prism (~> 1.4) 55 | rubocop-capybara (2.22.1) 56 | lint_roller (~> 1.1) 57 | rubocop (~> 1.72, >= 1.72.1) 58 | rubocop-discourse (3.12.1) 59 | activesupport (>= 6.1) 60 | lint_roller (>= 1.1.0) 61 | rubocop (>= 1.73.2) 62 | rubocop-capybara (>= 2.22.0) 63 | rubocop-factory_bot (>= 2.27.0) 64 | rubocop-rails (>= 2.30.3) 65 | rubocop-rspec (>= 3.0.1) 66 | rubocop-rspec_rails (>= 2.31.0) 67 | rubocop-factory_bot (2.27.1) 68 | lint_roller (~> 1.1) 69 | rubocop (~> 1.72, >= 1.72.1) 70 | rubocop-rails (2.32.0) 71 | activesupport (>= 4.2.0) 72 | lint_roller (~> 1.1) 73 | rack (>= 1.1) 74 | rubocop (>= 1.75.0, < 2.0) 75 | rubocop-ast (>= 1.44.0, < 2.0) 76 | rubocop-rspec (3.6.0) 77 | lint_roller (~> 1.1) 78 | rubocop (~> 1.72, >= 1.72.1) 79 | rubocop-rspec_rails (2.31.0) 80 | lint_roller (~> 1.1) 81 | rubocop (~> 1.72, >= 1.72.1) 82 | rubocop-rspec (~> 3.5) 83 | ruby-progressbar (1.13.0) 84 | securerandom (0.4.1) 85 | syntax_tree (6.2.0) 86 | prettier_print (>= 1.2.0) 87 | tzinfo (2.0.6) 88 | concurrent-ruby (~> 1.0) 89 | unicode-display_width (3.1.4) 90 | unicode-emoji (~> 4.0, >= 4.0.4) 91 | unicode-emoji (4.0.4) 92 | uri (1.0.3) 93 | 94 | PLATFORMS 95 | ruby 96 | 97 | DEPENDENCIES 98 | rubocop-discourse 99 | syntax_tree 100 | 101 | BUNDLED WITH 102 | 2.6.9 103 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Civilized Discourse Construction Kit, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Discourse RSS Polling [![Build Status](https://travis-ci.org/discourse/discourse-rss-polling.svg?branch=master)](https://travis-ci.org/discourse/discourse-rss-polling) 2 | 3 | Import RSS feeds from different sources into your Discourse. 4 | 5 | ## Install 6 | 7 | Add `git clone https://github.com/discourse/discourse-rss-polling.git` to the plugin section in your `app.yml` file. Please refer to [Install Plugins in Discourse](https://meta.discourse.org/t/install-plugins-in-discourse/19157) for installation instructions. 8 | 9 | Documentation can be found at [Configure the Discourse RSS Polling Plugin.](https://meta.discourse.org/t/configure-the-discourse-rss-polling-plugin/156387) 10 | -------------------------------------------------------------------------------- /app/controllers/discourse_rss_polling/feed_settings_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module DiscourseRssPolling 4 | class FeedSettingsController < Admin::AdminController 5 | requires_plugin "discourse-rss-polling" 6 | 7 | def show 8 | render json: FeedSettingFinder.all 9 | end 10 | 11 | def update 12 | feed = params[:feed_setting] 13 | 14 | if feed 15 | rss_feed = RssFeed.find_by_id(feed["id"]) || RssFeed.new 16 | 17 | rss_feed.assign_attributes( 18 | url: feed["feed_url"], 19 | author: feed["author_username"], 20 | category_id: feed["discourse_category_id"], 21 | tags: feed["discourse_tags"]&.join(","), 22 | category_filter: feed["feed_category_filter"], 23 | ) 24 | if rss_feed.save 25 | render json: { success: true } 26 | else 27 | render json: { success: false, errors: rss_feed.errors.full_messages }, status: 422 28 | end 29 | else 30 | render json: { success: false, error: "Invalid feed data" }, status: 400 31 | end 32 | end 33 | 34 | def destroy 35 | feed = params[:feed_setting] 36 | rss_feed = RssFeed.find_by_id(feed["id"]) 37 | 38 | if rss_feed 39 | rss_feed.destroy! 40 | render json: { success: true } 41 | else 42 | render json: { success: false, error: "Feed not found" }, status: 404 43 | end 44 | end 45 | 46 | private 47 | 48 | def feed_setting_params 49 | params.require(:feed_settings) 50 | end 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /app/jobs/jobs/discourse_rss_polling/fix_topic_embed_authors.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Jobs 4 | module DiscourseRssPolling 5 | class FixTopicEmbedAuthors < ::Jobs::Base 6 | sidekiq_options queue: "low" 7 | 8 | def mismatched_topic_embeds 9 | TopicEmbed.joins(post: :topic).where("posts.user_id != topics.user_id") 10 | end 11 | 12 | def execute(args) 13 | mismatched_topic_embeds.find_each do |topic_embed| 14 | post = topic_embed.post 15 | 16 | PostOwnerChanger.new( 17 | post_ids: [post.id], 18 | topic_id: post.topic_id, 19 | new_owner: post.user, 20 | acting_user: Discourse.system_user, 21 | skip_revision: true, 22 | ).change_owner! 23 | end 24 | end 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /app/jobs/jobs/discourse_rss_polling/poll_all_feeds.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Jobs 4 | module DiscourseRssPolling 5 | class PollAllFeeds < ::Jobs::Scheduled 6 | every 5.minutes 7 | 8 | def execute(args) 9 | return unless SiteSetting.rss_polling_enabled 10 | 11 | poll_all_feeds if not_polled_recently? 12 | end 13 | 14 | private 15 | 16 | def poll_all_feeds 17 | ::DiscourseRssPolling::FeedSettingFinder.all.each(&:poll) 18 | end 19 | 20 | REDIS_KEY = "rss-polling-feeds-polled" 21 | 22 | def not_polled_recently? 23 | Discourse.redis.set( 24 | REDIS_KEY, 25 | 1, 26 | ex: SiteSetting.rss_polling_frequency.minutes - 10.seconds, 27 | nx: true, 28 | ) 29 | end 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /app/jobs/jobs/discourse_rss_polling/poll_feed.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rss" 4 | 5 | module Jobs 6 | module DiscourseRssPolling 7 | class PollFeed < ::Jobs::Base 8 | def execute(args) 9 | return unless SiteSetting.rss_polling_enabled 10 | 11 | return unless @author = User.find_by_username(args[:author_username]) 12 | 13 | @discourse_category_id = args[:discourse_category_id] 14 | return if @discourse_category_id.present? && !Category.exists?(@discourse_category_id) 15 | 16 | @feed_url = args[:feed_url] 17 | @discourse_tags = args[:discourse_tags] 18 | @feed_category_filter = args[:feed_category_filter] 19 | 20 | poll_feed if not_polled_recently? 21 | end 22 | 23 | private 24 | 25 | attr_reader :feed_url, :author, :discourse_category_id, :discourse_tags, :feed_category_filter 26 | 27 | def feed_key 28 | "rss-polling-feed-polled:#{Digest::SHA1.hexdigest(feed_url)}" 29 | end 30 | 31 | def not_polled_recently? 32 | Discourse.redis.set( 33 | feed_key, 34 | 1, 35 | ex: SiteSetting.rss_polling_frequency.minutes - 10.seconds, 36 | nx: true, 37 | ) 38 | end 39 | 40 | def poll_feed 41 | topics_polled_from_feed.each do |feed_item| 42 | next if !feed_item.content.present? 43 | next if !feed_item.title.present? 44 | 45 | if ( 46 | feed_category_filter.present? && 47 | feed_item.categories.none? { |c| c.include?(feed_category_filter) } 48 | ) 49 | next 50 | end 51 | 52 | cook_method = feed_item.is_youtube? ? Post.cook_methods[:regular] : nil 53 | 54 | updated_tags = discourse_tags 55 | if !SiteSetting.rss_polling_update_tags 56 | url = TopicEmbed.normalize_url(feed_item.url) 57 | embed = TopicEmbed.topic_embed_by_url(url) 58 | topic_exists = embed.present? 59 | updated_tags = nil if topic_exists 60 | end 61 | 62 | post = 63 | TopicEmbed.import( 64 | author, 65 | feed_item.url, 66 | feed_item.title, 67 | CGI.unescapeHTML(feed_item.content), 68 | category_id: discourse_category_id, 69 | tags: updated_tags, 70 | cook_method: cook_method, 71 | ) 72 | if post && (post.created_at == post.updated_at) # new post 73 | if SiteSetting.rss_polling_use_pubdate 74 | begin 75 | post_time = feed_item.pubdate 76 | post.created_at = post_time 77 | post.save! 78 | post.topic.created_at = post_time 79 | post.topic.bumped_at = post_time 80 | post.topic.last_posted_at = post_time 81 | post.topic.save! 82 | rescue StandardError 83 | Rails.logger.error("Invalid pubDate for topic #{post.topic.id} #{post_time}") 84 | end 85 | end 86 | 87 | set_image_as_thumbnail(post, feed_item.image_link) if feed_item.image_link 88 | end 89 | end 90 | end 91 | 92 | def set_image_as_thumbnail(post, image_link) 93 | begin 94 | final_destination = FinalDestination.new(image_link) 95 | image_final_url = final_destination.resolve 96 | image_data = Excon.new(image_final_url.to_s).request(method: :get, expects: 200).body 97 | tmp = Tempfile.new("downloaded_image") 98 | tmp.binmode 99 | tmp.write(image_data) 100 | tmp.rewind 101 | source_filename = File.basename(URI.parse(image_final_url).path) 102 | upload = UploadCreator.new(tmp, source_filename).create_for(post.user.id) 103 | UploadReference.ensure_exist!(upload_ids: [upload.id], target: post) 104 | post.raw = "

#{post.raw}" 105 | post.save! 106 | post.rebake! 107 | rescue => e 108 | Rails.logger.error( 109 | "RSS Polling: Unable to download and save #{image_link} for post ##{post.id} #{e.message}", 110 | ) 111 | ensure 112 | begin 113 | tmp.close 114 | rescue StandardError 115 | nil 116 | end 117 | begin 118 | tmp.unlink 119 | rescue StandardError 120 | nil 121 | end 122 | end 123 | end 124 | 125 | def topics_polled_from_feed 126 | raw_feed = fetch_raw_feed 127 | return [] if raw_feed.blank? 128 | 129 | parsed_feed = RSS::Parser.parse(raw_feed, false) 130 | return [] if parsed_feed.blank? 131 | 132 | parsed_feed.items.map { |item| ::DiscourseRssPolling::FeedItem.new(item) } 133 | rescue RSS::NotWellFormedError, RSS::InvalidRSSError 134 | [] 135 | end 136 | 137 | def fetch_raw_feed 138 | final_destination = FinalDestination.new(@feed_url) 139 | feed_final_url = final_destination.resolve 140 | return nil unless final_destination.status == :resolved 141 | 142 | Excon.new(feed_final_url.to_s).request(method: :get, expects: 200).body 143 | rescue Excon::Error::HTTPStatus 144 | nil 145 | end 146 | end 147 | end 148 | end 149 | -------------------------------------------------------------------------------- /app/models/discourse_rss_polling/feed_item.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_dependency "feed_item_accessor" 4 | 5 | module DiscourseRssPolling 6 | class FeedItem 7 | def initialize(rss_item, accessor = ::FeedItemAccessor) 8 | @accessor = accessor.new(rss_item) 9 | end 10 | 11 | def url 12 | url?(@accessor.link) ? @accessor.link : @accessor.element_content(:id) 13 | end 14 | 15 | def content 16 | content = nil 17 | 18 | CONTENT_ELEMENT_TAG_NAMES.each do |tag_name| 19 | break if content = @accessor.element_content(tag_name) 20 | end 21 | 22 | return url if is_youtube? 23 | 24 | content&.force_encoding("UTF-8")&.scrub 25 | end 26 | 27 | def title 28 | unclean_title = @accessor.element_content(:title)&.force_encoding("UTF-8")&.scrub 29 | unclean_title = 30 | TextCleaner.clean_title(TextSentinel.title_sentinel(unclean_title).text).presence 31 | CGI.unescapeHTML(unclean_title) if unclean_title 32 | end 33 | 34 | def categories 35 | @accessor.element_content(:categories).map { |c| c.content } 36 | end 37 | 38 | def image_link 39 | @accessor.element_content(:itunes_image)&.href 40 | end 41 | 42 | def is_youtube? 43 | url&.starts_with?("https://www.youtube.com/watch") 44 | end 45 | 46 | def pubdate 47 | @accessor.element_content(:pubDate) || @accessor.element_content(:published) 48 | end 49 | 50 | private 51 | 52 | # The tag name's relative order implies its priority. 53 | CONTENT_ELEMENT_TAG_NAMES = %i[content_encoded content description summary] 54 | 55 | def url?(link) 56 | link.present? && link =~ %r{^https?\://} 57 | end 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /app/models/discourse_rss_polling/feed_setting.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module DiscourseRssPolling 4 | class FeedSetting 5 | include ActiveModel::Serialization 6 | 7 | attr_accessor( 8 | :id, 9 | :feed_url, 10 | :author_username, 11 | :discourse_category_id, 12 | :discourse_tags, 13 | :feed_category_filter, 14 | ) 15 | 16 | def initialize( 17 | id: nil, 18 | feed_url:, 19 | author_username:, 20 | discourse_category_id:, 21 | discourse_tags:, 22 | feed_category_filter: 23 | ) 24 | @id = id 25 | @feed_url = feed_url 26 | @author_username = author_username 27 | @discourse_category_id = discourse_category_id 28 | @discourse_tags = discourse_tags 29 | @feed_category_filter = feed_category_filter 30 | end 31 | 32 | def poll(inline: false) 33 | if inline 34 | Jobs::DiscourseRssPolling::PollFeed.new.execute( 35 | feed_url: feed_url, 36 | author_username: author_username, 37 | discourse_category_id: discourse_category_id, 38 | discourse_tags: discourse_tags, 39 | feed_category_filter: feed_category_filter, 40 | ) 41 | else 42 | Jobs.enqueue( 43 | "DiscourseRssPolling::PollFeed", 44 | feed_url: feed_url, 45 | author_username: author_username, 46 | discourse_category_id: discourse_category_id, 47 | discourse_tags: discourse_tags, 48 | feed_category_filter: feed_category_filter, 49 | ) 50 | end 51 | end 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /app/models/discourse_rss_polling/rss_feed.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module DiscourseRssPolling 4 | class RssFeed < ActiveRecord::Base 5 | validates :url, presence: true 6 | end 7 | end 8 | 9 | # == Schema Information 10 | # 11 | # Table name: discourse_rss_polling_rss_feeds 12 | # 13 | # id :bigint not null, primary key 14 | # url :string not null 15 | # category_filter :string 16 | # author :string 17 | # category_id :integer 18 | # tags :string 19 | # created_at :datetime not null 20 | # updated_at :datetime not null 21 | # 22 | -------------------------------------------------------------------------------- /app/services/discourse_rss_polling/feed_setting_finder.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module DiscourseRssPolling 4 | class FeedSettingFinder 5 | def self.by_embed_url(embed_url) 6 | host = URI.parse(embed_url).host.sub(/^www\./, "") 7 | feed = RssFeed.where("url LIKE ?", "%#{host}%").first 8 | return nil if !feed 9 | FeedSetting.new( 10 | id: feed.id, 11 | feed_url: feed.url, 12 | author_username: feed.author, 13 | discourse_category_id: feed.category_id, 14 | discourse_tags: feed.tags.nil? ? nil : feed.tags.split(","), 15 | feed_category_filter: feed.category_filter, 16 | ) 17 | end 18 | 19 | def self.all 20 | new.all 21 | end 22 | 23 | def initialize 24 | @condition = Proc.new { |*| true } 25 | end 26 | 27 | def where(&block) 28 | @condition = block 29 | self 30 | end 31 | 32 | def all 33 | RssFeed.all.map do |feed| 34 | FeedSetting.new( 35 | id: feed.id, 36 | feed_url: feed.url, 37 | author_username: feed.author, 38 | discourse_category_id: feed.category_id, 39 | discourse_tags: feed.tags.nil? ? nil : feed.tags.split(","), 40 | feed_category_filter: feed.category_filter, 41 | ) 42 | end 43 | end 44 | 45 | def take 46 | all&.first 47 | end 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /assets/javascripts/admin/models/rss-polling-feed-settings.js: -------------------------------------------------------------------------------- 1 | import { ajax } from "discourse/lib/ajax"; 2 | 3 | export default { 4 | show() { 5 | return ajax("/admin/plugins/rss_polling/feed_settings.json"); 6 | }, 7 | 8 | updateFeed(feedSetting) { 9 | return ajax("/admin/plugins/rss_polling/feed_settings", { 10 | type: "PUT", 11 | contentType: "application/json", 12 | processData: false, 13 | data: JSON.stringify({ feed_setting: feedSetting }), 14 | }); 15 | }, 16 | 17 | deleteFeed(feedSetting) { 18 | return ajax("/admin/plugins/rss_polling/feed_settings", { 19 | type: "DELETE", 20 | contentType: "application/json", 21 | processData: false, 22 | data: JSON.stringify({ feed_setting: feedSetting }), 23 | }); 24 | }, 25 | }; 26 | -------------------------------------------------------------------------------- /assets/javascripts/discourse/controllers/admin-plugins-rss-polling.js: -------------------------------------------------------------------------------- 1 | import Controller from "@ember/controller"; 2 | import { action, set } from "@ember/object"; 3 | import { alias } from "@ember/object/computed"; 4 | import { service } from "@ember/service"; 5 | import { isBlank } from "@ember/utils"; 6 | import { observes } from "@ember-decorators/object"; 7 | import { popupAjaxError } from "discourse/lib/ajax-error"; 8 | import discourseComputed from "discourse/lib/decorators"; 9 | import { i18n } from "discourse-i18n"; 10 | import RssPollingFeedSettings from "../../admin/models/rss-polling-feed-settings"; 11 | 12 | export default class AdminPluginsRssPollingController extends Controller { 13 | @service dialog; 14 | 15 | @alias("model") feedSettings; 16 | 17 | saving = false; 18 | valid = false; 19 | disabled = true; 20 | 21 | @discourseComputed("valid", "saving") 22 | unsavable(valid, saving) { 23 | return !valid || saving; 24 | } 25 | 26 | // TODO: extract feed setting into its own component && more validation 27 | @observes("feedSettings.@each.{feed_url,author_username}") 28 | validate() { 29 | let overallValidity = true; 30 | 31 | this.get("feedSettings").forEach((feedSetting) => { 32 | const localValidity = 33 | !isBlank(feedSetting.feed_url) && !isBlank(feedSetting.author_username); 34 | set(feedSetting, "valid", localValidity); 35 | overallValidity = overallValidity && localValidity; 36 | }); 37 | 38 | this.set("valid", overallValidity); 39 | } 40 | 41 | @action 42 | create() { 43 | let newSetting = { 44 | feed_url: null, 45 | author_username: null, 46 | discourse_category_id: null, 47 | discourse_tags: null, 48 | feed_category_filter: null, 49 | disabled: false, 50 | editing: true, 51 | }; 52 | 53 | this.get("feedSettings").addObject(newSetting); 54 | } 55 | 56 | @action 57 | destroyFeedSetting(setting) { 58 | this.dialog.deleteConfirm({ 59 | message: i18n("admin.rss_polling.destroy_feed.confirm"), 60 | didConfirm: async () => { 61 | try { 62 | await RssPollingFeedSettings.deleteFeed(setting); 63 | this.get("feedSettings").removeObject(setting); 64 | } catch (error) { 65 | popupAjaxError(error); 66 | } finally { 67 | this.set("saving", false); 68 | } 69 | }, 70 | }); 71 | } 72 | 73 | @action 74 | editFeedSetting(setting) { 75 | set(setting, "disabled", false); 76 | set(setting, "editing", true); 77 | } 78 | 79 | @action 80 | cancelEdit(setting) { 81 | if (!setting.id) { 82 | this.get("feedSettings").removeObject(setting); 83 | } 84 | set(setting, "disabled", true); 85 | set(setting, "editing", false); 86 | } 87 | 88 | @action 89 | async updateFeedSetting(setting) { 90 | this.set("saving", true); 91 | 92 | try { 93 | await RssPollingFeedSettings.updateFeed(setting); 94 | } catch (error) { 95 | popupAjaxError(error); 96 | } finally { 97 | this.set("saving", false); 98 | set(setting, "disabled", true); 99 | set(setting, "editing", false); 100 | } 101 | } 102 | 103 | @action 104 | updateAuthorUsername(setting, selected) { 105 | set(setting, "author_username", selected.firstObject); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /assets/javascripts/discourse/routes/admin-plugins-rss-polling.js: -------------------------------------------------------------------------------- 1 | import DiscourseRoute from "discourse/routes/discourse"; 2 | import RssPollingFeedSettings from "../../admin/models/rss-polling-feed-settings"; 3 | 4 | export default class AdminPluginsRssPolling extends DiscourseRoute { 5 | model() { 6 | return RssPollingFeedSettings.show().then((result) => result.feed_settings); 7 | } 8 | 9 | setupController(controller, model) { 10 | model.forEach((setting) => { 11 | setting.disabled = true; 12 | setting.editing = false; 13 | }); 14 | 15 | controller.setProperties({ 16 | model, 17 | }); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /assets/javascripts/discourse/rss-polling-route-map.js: -------------------------------------------------------------------------------- 1 | export default { 2 | resource: "admin.adminPlugins", 3 | path: "/plugins", 4 | map() { 5 | this.route("rss_polling"); 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /assets/javascripts/discourse/templates/admin/plugins-rss-polling.gjs: -------------------------------------------------------------------------------- 1 | import { Input } from "@ember/component"; 2 | import { fn, hash } from "@ember/helper"; 3 | import RouteTemplate from "ember-route-template"; 4 | import DButton from "discourse/components/d-button"; 5 | import { i18n } from "discourse-i18n"; 6 | import CategoryChooser from "select-kit/components/category-chooser"; 7 | import EmailGroupUserChooser from "select-kit/components/email-group-user-chooser"; 8 | import TagChooser from "select-kit/components/tag-chooser"; 9 | 10 | export default RouteTemplate( 11 | 130 | ); 131 | -------------------------------------------------------------------------------- /assets/stylesheets/rss-polling.scss: -------------------------------------------------------------------------------- 1 | .rss-polling-feed-settings { 2 | table { 3 | tr { 4 | td { 5 | position: relative; 6 | 7 | &:first-child input { 8 | max-width: 200px; 9 | } 10 | 11 | &:nth-child(2) input { 12 | max-width: 100px; 13 | } 14 | 15 | .user-chooser, 16 | .category-chooser { 17 | max-width: 150px; 18 | } 19 | 20 | input { 21 | margin-bottom: 0; 22 | } 23 | 24 | .select-kit.multi-select { 25 | width: 120px; 26 | } 27 | } 28 | } 29 | 30 | .wide-button { 31 | width: 100%; 32 | text-align: center; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /config/locales/client.ar.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | ar: 8 | -------------------------------------------------------------------------------- /config/locales/client.be.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | be: 8 | -------------------------------------------------------------------------------- /config/locales/client.bg.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | bg: 8 | -------------------------------------------------------------------------------- /config/locales/client.bs_BA.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | bs_BA: 8 | -------------------------------------------------------------------------------- /config/locales/client.ca.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | ca: 8 | -------------------------------------------------------------------------------- /config/locales/client.cs.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | cs: 8 | -------------------------------------------------------------------------------- /config/locales/client.da.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | da: 8 | -------------------------------------------------------------------------------- /config/locales/client.de.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | de: 8 | admin_js: 9 | admin: 10 | site_settings: 11 | categories: 12 | discourse_rss_polling: "Discourse-RSS-Abfrage" 13 | js: 14 | rss_polling: 15 | title: RSS-Abfrage 16 | admin: 17 | rss_polling: 18 | feed: Feed-Einstellungen 19 | discourse: Discourse Einstellungen 20 | author: Autor 21 | feed_url: URL 22 | discourse_category: Kategorie 23 | discourse_tags: Schlagwörter 24 | feed_category_filter: Kategoriefilter 25 | documentation: Dokumentation zur Konfiguration von RSS-Abfrage 26 | destroy_feed: 27 | confirm: "Bist du sicher, dass du diesen Feed löschen möchtest?" 28 | -------------------------------------------------------------------------------- /config/locales/client.el.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | el: 8 | -------------------------------------------------------------------------------- /config/locales/client.en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | admin_js: 3 | admin: 4 | site_settings: 5 | categories: 6 | discourse_rss_polling: "Discourse RSS Polling" 7 | js: 8 | rss_polling: 9 | title: RSS Polling 10 | 11 | admin: 12 | rss_polling: 13 | feed: Feed Settings 14 | discourse: Discourse Settings 15 | author: Author 16 | feed_url: URL 17 | discourse_category: Category 18 | discourse_tags: Tags 19 | feed_category_filter: Category Filter 20 | documentation: RSS Polling configuration documentation 21 | destroy_feed: 22 | confirm: "Are you sure you want to delete this feed?" 23 | -------------------------------------------------------------------------------- /config/locales/client.en_GB.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | en_GB: 8 | -------------------------------------------------------------------------------- /config/locales/client.es.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | es: 8 | -------------------------------------------------------------------------------- /config/locales/client.et.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | et: 8 | -------------------------------------------------------------------------------- /config/locales/client.fa_IR.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | fa_IR: 8 | -------------------------------------------------------------------------------- /config/locales/client.fi.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | fi: 8 | -------------------------------------------------------------------------------- /config/locales/client.fr.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | fr: 8 | -------------------------------------------------------------------------------- /config/locales/client.gl.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | gl: 8 | -------------------------------------------------------------------------------- /config/locales/client.he.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | he: 8 | admin_js: 9 | admin: 10 | site_settings: 11 | categories: 12 | discourse_rss_polling: "משיכת RSS ב־Discourse" 13 | js: 14 | rss_polling: 15 | title: משיכת RSS 16 | admin: 17 | rss_polling: 18 | feed: הגדרות ערוץ 19 | discourse: הגדרות Discourse 20 | author: מחבר/ת 21 | feed_url: כתובת 22 | discourse_category: קטגוריה 23 | discourse_tags: תגיות 24 | feed_category_filter: מסנן קטגוריה 25 | documentation: תיעוד הגדרות משיכת RSS 26 | destroy_feed: 27 | confirm: "למחוק את הערוץ הזה?" 28 | -------------------------------------------------------------------------------- /config/locales/client.hr.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | hr: 8 | -------------------------------------------------------------------------------- /config/locales/client.hu.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | hu: 8 | -------------------------------------------------------------------------------- /config/locales/client.hy.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | hy: 8 | -------------------------------------------------------------------------------- /config/locales/client.id.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | id: 8 | -------------------------------------------------------------------------------- /config/locales/client.it.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | it: 8 | -------------------------------------------------------------------------------- /config/locales/client.ja.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | ja: 8 | -------------------------------------------------------------------------------- /config/locales/client.ko.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | ko: 8 | -------------------------------------------------------------------------------- /config/locales/client.lt.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | lt: 8 | -------------------------------------------------------------------------------- /config/locales/client.lv.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | lv: 8 | -------------------------------------------------------------------------------- /config/locales/client.nb_NO.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | nb_NO: 8 | -------------------------------------------------------------------------------- /config/locales/client.nl.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | nl: 8 | -------------------------------------------------------------------------------- /config/locales/client.pl_PL.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | pl_PL: 8 | admin_js: 9 | admin: 10 | site_settings: 11 | categories: 12 | discourse_rss_polling: "Pobieranie RSS w Discourse" 13 | js: 14 | rss_polling: 15 | title: Pobieranie RSS 16 | admin: 17 | rss_polling: 18 | feed: Ustawienia kanału 19 | discourse: Ustawienia Discourse 20 | author: Autor 21 | feed_url: URL 22 | discourse_category: Kategoria 23 | discourse_tags: Tagi 24 | feed_category_filter: Filtr kategorii 25 | documentation: Dokumentacja konfiguracji pobierania RSS 26 | destroy_feed: 27 | confirm: "Czy na pewno chcesz usunąć ten kanał?" 28 | -------------------------------------------------------------------------------- /config/locales/client.pt.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | pt: 8 | -------------------------------------------------------------------------------- /config/locales/client.pt_BR.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | pt_BR: 8 | -------------------------------------------------------------------------------- /config/locales/client.ro.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | ro: 8 | admin_js: 9 | admin: 10 | site_settings: 11 | categories: 12 | discourse_rss_polling: "Interogare RSS Discourse" 13 | js: 14 | rss_polling: 15 | title: Interogare RSS 16 | admin: 17 | rss_polling: 18 | feed: Setări flux 19 | discourse: Setări Discourse 20 | author: Autor 21 | feed_url: URL 22 | discourse_category: Categorie 23 | discourse_tags: Etichete 24 | feed_category_filter: Filtru de categorie 25 | documentation: Documentație de configurare a interogării RSS 26 | destroy_feed: 27 | confirm: "Sigur vrei să ștergi acest flux?" 28 | -------------------------------------------------------------------------------- /config/locales/client.ru.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | ru: 8 | -------------------------------------------------------------------------------- /config/locales/client.sk.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | sk: 8 | -------------------------------------------------------------------------------- /config/locales/client.sl.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | sl: 8 | -------------------------------------------------------------------------------- /config/locales/client.sq.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | sq: 8 | -------------------------------------------------------------------------------- /config/locales/client.sr.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | sr: 8 | -------------------------------------------------------------------------------- /config/locales/client.sv.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | sv: 8 | -------------------------------------------------------------------------------- /config/locales/client.sw.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | sw: 8 | -------------------------------------------------------------------------------- /config/locales/client.te.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | te: 8 | -------------------------------------------------------------------------------- /config/locales/client.th.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | th: 8 | -------------------------------------------------------------------------------- /config/locales/client.tr_TR.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | tr_TR: 8 | -------------------------------------------------------------------------------- /config/locales/client.ug.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | ug: 8 | -------------------------------------------------------------------------------- /config/locales/client.uk.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | uk: 8 | -------------------------------------------------------------------------------- /config/locales/client.ur.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | ur: 8 | -------------------------------------------------------------------------------- /config/locales/client.vi.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | vi: 8 | -------------------------------------------------------------------------------- /config/locales/client.zh_CN.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | zh_CN: 8 | -------------------------------------------------------------------------------- /config/locales/client.zh_TW.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | zh_TW: 8 | -------------------------------------------------------------------------------- /config/locales/server.ar.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | ar: 8 | -------------------------------------------------------------------------------- /config/locales/server.be.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | be: 8 | -------------------------------------------------------------------------------- /config/locales/server.bg.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | bg: 8 | -------------------------------------------------------------------------------- /config/locales/server.bs_BA.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | bs_BA: 8 | -------------------------------------------------------------------------------- /config/locales/server.ca.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | ca: 8 | site_settings: 9 | rss_polling_frequency: "[RSS Polling] Freqüència del mostratge del canal (en minuts)" 10 | -------------------------------------------------------------------------------- /config/locales/server.cs.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | cs: 8 | site_settings: 9 | rss_polling_frequency: "[RSS Polling] Frekvece feed pollingu (v minutách)" 10 | -------------------------------------------------------------------------------- /config/locales/server.da.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | da: 8 | site_settings: 9 | rss_polling_frequency: "[RSS Polling] Frekvens af 'feed polling' (i minutter)" 10 | -------------------------------------------------------------------------------- /config/locales/server.de.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | de: 8 | site_settings: 9 | rss_polling_enabled: "[RSS-Abfrage] Importieren von eingebetteten Beiträgen aus mehreren RSS-Feeds ermöglichen" 10 | rss_polling_frequency: "[RSS Abfrage] Häufigkeit der Feed-Abfrage (in Minuten)" 11 | rss_polling_use_pubdate: "[RSS-Abfrage] Setze das Erstellungsdatum des Themas auf das im RSS-Feed gefundene Veröffentlichungsdatum" 12 | rss_polling_update_tags: "[RSS Abfrage] Aktualisiere Schlagwörter des Themas, wenn es aktualisiert wird. Wenn du diese Option deaktivierst, werden die ursprünglichen Schlagwörter übernommen, aber weitere Änderungen nicht mehr vorgenommen." 13 | -------------------------------------------------------------------------------- /config/locales/server.el.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | el: 8 | site_settings: 9 | rss_polling_frequency: "[RSS Polling] Συχνότητα του feed polling (σε λεπτά)" 10 | -------------------------------------------------------------------------------- /config/locales/server.en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | site_settings: 3 | rss_polling_enabled: "[RSS Polling] Enable importing embed posts from multiple RSS feeds" 4 | rss_polling_frequency: "[RSS Polling] Feed polling frequency, in minutes" 5 | rss_polling_use_pubdate: "[RSS Polling] Set topic creation date to the pubDate found in the RSS feed" 6 | rss_polling_update_tags: "[RSS Polling] Update topic tags when a topic is updated. Disabling this pulls initial tags but disables further tag changes." 7 | -------------------------------------------------------------------------------- /config/locales/server.en_GB.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | en_GB: 8 | -------------------------------------------------------------------------------- /config/locales/server.es.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | es: 8 | site_settings: 9 | rss_polling_frequency: "[RSS Polling] Frecuencia del feed de la encuesta (en minutos)" 10 | -------------------------------------------------------------------------------- /config/locales/server.et.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | et: 8 | -------------------------------------------------------------------------------- /config/locales/server.fa_IR.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | fa_IR: 8 | site_settings: 9 | rss_polling_frequency: "[RSS Polling] تعداد دفعات رای گیری خوراک (به دقیقه)" 10 | -------------------------------------------------------------------------------- /config/locales/server.fi.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | fi: 8 | site_settings: 9 | rss_polling_frequency: "[RSS Polling] Syötteen kyselyn taajuus (minuutteina)" 10 | -------------------------------------------------------------------------------- /config/locales/server.fr.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | fr: 8 | site_settings: 9 | rss_polling_frequency: "[RSS Polling] Fréquence de rafraichissement du flux (en minutes)" 10 | -------------------------------------------------------------------------------- /config/locales/server.gl.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | gl: 8 | -------------------------------------------------------------------------------- /config/locales/server.he.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | he: 8 | site_settings: 9 | rss_polling_enabled: "[משיכת RSS] הפעלת ייבוא והטמעת פוסטים ממגוון ערוצי RSS" 10 | rss_polling_frequency: "[משיכת RSS] תדירות משיכת ערוץ, בדקות" 11 | rss_polling_use_pubdate: "[משיכת RSS] להגדיר תאריך יצירת נושאים ל־pubDate (תאריך פרסום) שנמצא בערוץ ה־RSS" 12 | rss_polling_update_tags: "[משיכת RSS] לעדכן תגיות נושאים כאשר נושא מתעדכן. השבתת האפשרות הזאת מושכת תגיות ראשוניות אבל משביתה שינויים נוספים בתגיות." 13 | -------------------------------------------------------------------------------- /config/locales/server.hr.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | hr: 8 | -------------------------------------------------------------------------------- /config/locales/server.hu.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | hu: 8 | -------------------------------------------------------------------------------- /config/locales/server.hy.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | hy: 8 | site_settings: 9 | rss_polling_frequency: "[RSS Polling] Լրահոսի հարցման հաճախականությունը (րոպեներով)" 10 | -------------------------------------------------------------------------------- /config/locales/server.id.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | id: 8 | -------------------------------------------------------------------------------- /config/locales/server.it.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | it: 8 | site_settings: 9 | rss_polling_frequency: "[RSS Polling] Frequenza del feed polling (in minuti)" 10 | -------------------------------------------------------------------------------- /config/locales/server.ja.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | ja: 8 | site_settings: 9 | rss_polling_frequency: "[RSS Polling] フィードの更新間隔 (分)" 10 | -------------------------------------------------------------------------------- /config/locales/server.ko.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | ko: 8 | site_settings: 9 | rss_polling_frequency: "[RSS Polling] 피드 폴링 빈도(분당)" 10 | -------------------------------------------------------------------------------- /config/locales/server.lt.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | lt: 8 | -------------------------------------------------------------------------------- /config/locales/server.lv.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | lv: 8 | site_settings: 9 | rss_polling_frequency: "[RSS Polling] Aptauju biežums (minūtēs)" 10 | -------------------------------------------------------------------------------- /config/locales/server.nb_NO.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | nb_NO: 8 | site_settings: 9 | rss_polling_frequency: "[RSS Polling] Frekvens for strømspørring (i minutter)" 10 | -------------------------------------------------------------------------------- /config/locales/server.nl.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | nl: 8 | site_settings: 9 | rss_polling_frequency: "[RSS Polling] Hoe vaak feed verversen (in minuten)" 10 | -------------------------------------------------------------------------------- /config/locales/server.pl_PL.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | pl_PL: 8 | site_settings: 9 | rss_polling_enabled: "[Ankieta RSS] Włącz importowanie osadzonych postów z wielu kanałów RSS" 10 | rss_polling_frequency: "[RSS Polling] Częstotliwość aktualizacji strony (w minutach)" 11 | rss_polling_use_pubdate: "[RSS Polling] Ustaw datę utworzenia tematu na pubDate znalezioną w kanale RSS." 12 | rss_polling_update_tags: "[RSS Polling] Aktualizuj tagi tematów, gdy temat jest aktualizowany. Wyłączenie tej opcji pobiera początkowe tagi, ale wyłącza dalsze zmiany tagów." 13 | -------------------------------------------------------------------------------- /config/locales/server.pt.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | pt: 8 | -------------------------------------------------------------------------------- /config/locales/server.pt_BR.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | pt_BR: 8 | site_settings: 9 | rss_polling_frequency: "[RSS Polling] Frequência de pesquisa de feeds (em minutos)" 10 | -------------------------------------------------------------------------------- /config/locales/server.ro.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | ro: 8 | site_settings: 9 | rss_polling_enabled: "[Interogare RSS] Activează importarea postărilor încorporate din mai multe fluxuri RSS" 10 | rss_polling_frequency: "[Interogare RSS] Frecvența de interogare a fluxului, în minute" 11 | rss_polling_use_pubdate: "[Interogare RSS] Setează data creării subiectului la pubDate găsit în fluxul RSS" 12 | rss_polling_update_tags: "[Interogare RSS] Actualizează etichetele subiectului când un subiect este actualizat. Dezactivarea acesteia retrage etichetele inițiale, dar dezactivează modificările ulterioare ale etichetelor." 13 | -------------------------------------------------------------------------------- /config/locales/server.ru.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | ru: 8 | site_settings: 9 | rss_polling_frequency: "[RSS Polling] Частота опроса ленты (в минутах)" 10 | -------------------------------------------------------------------------------- /config/locales/server.sk.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | sk: 8 | -------------------------------------------------------------------------------- /config/locales/server.sl.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | sl: 8 | -------------------------------------------------------------------------------- /config/locales/server.sq.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | sq: 8 | -------------------------------------------------------------------------------- /config/locales/server.sr.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | sr: 8 | -------------------------------------------------------------------------------- /config/locales/server.sv.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | sv: 8 | -------------------------------------------------------------------------------- /config/locales/server.sw.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | sw: 8 | site_settings: 9 | rss_polling_frequency: "[RSS Polling] Uchaguzi wa taarifa unarudia mara (ndani ya dakika)" 10 | -------------------------------------------------------------------------------- /config/locales/server.te.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | te: 8 | -------------------------------------------------------------------------------- /config/locales/server.th.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | th: 8 | -------------------------------------------------------------------------------- /config/locales/server.tr_TR.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | tr_TR: 8 | site_settings: 9 | rss_polling_frequency: "[RSS Polling] Besleme yoklama sıklığı (dakika cinsinden)" 10 | -------------------------------------------------------------------------------- /config/locales/server.ug.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | ug: 8 | -------------------------------------------------------------------------------- /config/locales/server.uk.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | uk: 8 | -------------------------------------------------------------------------------- /config/locales/server.ur.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | ur: 8 | site_settings: 9 | rss_polling_frequency: "[RSS Polling] فیڈ پولنگ کی فریکوئینسی (منٹوں میں)" 10 | -------------------------------------------------------------------------------- /config/locales/server.vi.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | vi: 8 | -------------------------------------------------------------------------------- /config/locales/server.zh_CN.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | zh_CN: 8 | site_settings: 9 | rss_polling_frequency: "[RSS Polling] 消息轮询频率(分钟)" 10 | -------------------------------------------------------------------------------- /config/locales/server.zh_TW.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | zh_TW: 8 | site_settings: 9 | rss_polling_frequency: "[RSS Polling] 訊息更新頻率(分鐘)" 10 | -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | DiscourseRssPolling::Engine.routes.draw do 4 | root "feed_settings#show" 5 | 6 | resource :feed_settings, constraints: StaffConstraint.new, only: %i[show update destroy] 7 | end 8 | -------------------------------------------------------------------------------- /config/settings.yml: -------------------------------------------------------------------------------- 1 | plugins: 2 | rss_polling_enabled: 3 | default: false 4 | shadowed_by_global: true 5 | 6 | # This stores a YAML serialized array of feed setting tuples, in the format of 7 | # [feed_url, author_username] 8 | rss_polling_feed_setting: 9 | default: "[]" 10 | hidden: true 11 | client: false 12 | 13 | rss_polling_frequency: 14 | min: 10 15 | max: 180 16 | default: 30 17 | client: false 18 | 19 | rss_polling_use_pubdate: 20 | default: false 21 | client: false 22 | 23 | rss_polling_update_tags: 24 | default: true 25 | client: false -------------------------------------------------------------------------------- /db/migrate/20180828095129_push_fix_topic_embed_authors_job.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PushFixTopicEmbedAuthorsJob < ActiveRecord::Migration[5.2] 4 | def change 5 | Jobs.enqueue("DiscourseRssPolling::FixTopicEmbedAuthors") 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20230318130154_create_discourse_rss_polling_rss_feeds.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class CreateDiscourseRssPollingRssFeeds < ActiveRecord::Migration[7.0] 4 | def change 5 | create_table :discourse_rss_polling_rss_feeds do |t| 6 | t.string :url, null: false, length: 255 7 | t.string :category_filter, length: 100 8 | t.string :author, length: 100 9 | t.integer :category_id 10 | t.string :tags, length: 255 11 | t.timestamps 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /db/migrate/20230319115620_move_rss_yaml_to_db.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class MoveRssYamlToDb < ActiveRecord::Migration[7.0] 4 | def up 5 | rss_polling_feed_setting = 6 | DB 7 | .query("SELECT * FROM site_settings WHERE name = 'rss_polling_feed_setting' LIMIT 1") 8 | .first 9 | &.value || "" 10 | begin 11 | feeds = YAML.safe_load(rss_polling_feed_setting) 12 | feeds&.each do |(url, author, category_id, tags, category_filter)| 13 | tags = tags&.join(",") 14 | 15 | DiscourseRssPolling::RssFeed.create(url:, author:, category_id:, tags:, category_filter:) 16 | rescue Psych::SyntaxError => ex 17 | # We don't want the migration to fail if invalid yaml exists for some reason 18 | end 19 | end 20 | end 21 | 22 | def down 23 | raise ActiveRecord::IrreversibleMigration 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import DiscourseRecommended from "@discourse/lint-configs/eslint"; 2 | 3 | export default [...DiscourseRecommended]; 4 | -------------------------------------------------------------------------------- /lib/discourse_rss_polling/engine.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module DiscourseRssPolling 4 | class Engine < ::Rails::Engine 5 | engine_name "discourse_rss_polling" 6 | isolate_namespace DiscourseRssPolling 7 | 8 | config.to_prepare do 9 | Dir[ 10 | File.expand_path(File.join("..", "..", "..", "app", "jobs", "**", "*.rb"), __FILE__) 11 | ].each { |job| require_dependency job } 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "devDependencies": { 4 | "@discourse/lint-configs": "2.23.0", 5 | "ember-template-lint": "7.7.0", 6 | "eslint": "9.28.0", 7 | "prettier": "3.5.3", 8 | "stylelint": "16.20.0" 9 | }, 10 | "engines": { 11 | "node": ">= 22", 12 | "npm": "please-use-pnpm", 13 | "yarn": "please-use-pnpm", 14 | "pnpm": "9.x" 15 | }, 16 | "packageManager": "pnpm@9.15.5" 17 | } 18 | -------------------------------------------------------------------------------- /plugin.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # name: discourse-rss-polling 4 | # about: This plugin enables support for importing embedded content from multiple RSS/ATOM feeds 5 | # version: 0.0.1 6 | # authors: xrav3nz 7 | # url: https://github.com/discourse/discourse-rss-polling 8 | 9 | require_relative "lib/discourse_rss_polling/engine" 10 | 11 | enabled_site_setting :rss_polling_enabled 12 | add_admin_route "rss_polling.title", "rss_polling" 13 | register_asset "stylesheets/rss-polling.scss" 14 | register_svg_icon "floppy-disk" if respond_to?(:register_svg_icon) 15 | 16 | Discourse::Application.routes.append do 17 | mount ::DiscourseRssPolling::Engine, at: "/admin/plugins/rss_polling" 18 | end 19 | -------------------------------------------------------------------------------- /spec/fixtures/files/escaped_html.atom: -------------------------------------------------------------------------------- 1 | 2 | 4 | Discourse 5 | 6 | 2019-08-21T01:42:02Z 7 | https://blog.discourse.org/feed/atom/ 8 | 9 | https://blog.discourse.org/?p=pollfeedspec 10 | <![CDATA[Wellington: “Progress is hard!” Other cities: “Hold my beer”]]> 11 | 12 | xrav3nz 13 | 14 | 15 | 2019-08-16T21:46:39Z 16 | 2019-08-16T21:46:39Z 17 | Here are some random descriptions... 18 | 19 | 20 | -------------------------------------------------------------------------------- /spec/fixtures/files/mastodon.rss: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Foo Bar 5 | Public posts from @foo@mathstodon.bar 6 | https://mathstodon.bar/@foo 7 | 8 | https://mathstodon.bar/avatars/original/missing.png 9 | Foo Bar 10 | https://mathstodon.bar/@foo 11 | 12 | Wed, 29 Mar 2023 20:01:49 +0000 13 | https://mathstodon.bar/avatars/original/missing.png 14 | Mastodon v4.2.10 15 | 16 | https://mathstodon.bar/@foo/123456789 17 | https://mathstodon.bar/@foo/123456789 18 | Wed, 29 Mar 2023 19:02:42 +0000 19 | Test 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /spec/fixtures/files/multiple_categories.atom: -------------------------------------------------------------------------------- 1 | 2 | 4 | Discourse 5 | 6 | 2019-08-21T01:42:02Z 7 | https://blog.discourse.org/feed/atom/ 8 | 9 | https://blog.discourse.org/?p=pollfeedspec 10 | Poll Feed Spec Fixture 11 | 12 | xrav3nz 13 | 14 | spec 15 | xrav3nz diary 16 | 17 | 2019-08-16T21:46:39Z 18 | 2019-08-16T21:46:39Z 19 | Here are some random descriptions... 20 | 21 | 22 | -------------------------------------------------------------------------------- /spec/fixtures/files/no_content_only_summary.atom: -------------------------------------------------------------------------------- 1 | 2 | 4 | Discourse 5 | 6 | 2019-08-21T01:42:02Z 7 | https://blog.discourse.org/feed/atom/ 8 | 9 | https://blog.discourse.org/?p=pollfeedspec 10 | Poll Feed Spec Fixture 11 | 12 | xrav3nz 13 | 14 | 15 | 2019-08-16T21:46:39Z 16 | 2019-08-16T21:46:39Z 17 | Here are some random descriptions... 18 | 19 | 20 | -------------------------------------------------------------------------------- /spec/fixtures/files/youtube_channel.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | yt:channel:UCXuqSBlHAE6Xw-yeJA0Tunw 5 | UCXuqSBlHAE6Xw-yeJA0Tunw 6 | Linus Tech Tips 7 | 8 | 9 | Linus Tech Tips 10 | https://www.youtube.com/channel/UCXuqSBlHAE6Xw-yeJA0Tunw 11 | 12 | 2008-11-25T00:46:52+00:00 13 | 14 | yt:video:peYYl2vrIt4 15 | peYYl2vrIt4 16 | UCXuqSBlHAE6Xw-yeJA0Tunw 17 | An Uncontroversial Opinion – AMD RX 6600 XT Announcement 18 | 19 | 20 | Linus Tech Tips 21 | https://www.youtube.com/channel/UCXuqSBlHAE6Xw-yeJA0Tunw 22 | 23 | 2021-07-30T03:30:01+00:00 24 | 2021-07-30T16:20:48+00:00 25 | 26 | An Uncontroversial Opinion – AMD RX 6600 XT Announcement 27 | 28 | 29 | Start your build today at https://www.buildredux.com/linus 30 | 31 | Buy a Seasonic Ultra Titanium Power Supply: 32 | On Amazon: https://geni.us/q4lnefC 33 | On NewEgg: https://lmg.gg/8KV3S 34 | 35 | AMD’s latest – but perhaps not greatest – GPU has finally been officially confirmed, but the GPU isn’t the big news... What does this mean for the GPU market as a whole? 36 | 37 | 38 | Discuss on the forum: https://linustechtips.com/topic/1360741-an-uncontroversial-opinion-%E2%80%93-amd-rx-6600-xt-announcement/ 39 | 40 | 41 | ►GET MERCH: http://www.LTTStore.com/ 42 | ►SUPPORT US ON FLOATPLANE: https://www.floatplane.com/ 43 | ►LTX EXPO: https://www.ltxexpo.com/ 44 | 45 | AFFILIATES & REFERRALS 46 | --------------------------------------------------- 47 | ►Affiliates, Sponsors & Referrals: https://lmg.gg/sponsors 48 | ►Check out our podcast gear: https://kit.co/linustechtips/lmg-podcast-gear 49 | ►Private Internet Access VPN: https://lmg.gg/pialinus2 50 | ►Our Official Charging Partner Anker: https://lmg.gg/AnkerLTT 51 | ►MK Keyboards: https://lmg.gg/LyLtl 52 | ►Nerd or Die Stream Overlays: https://lmg.gg/avLlO 53 | ►Official Game Store: https://www.nexus.gg/ltt 54 | ►Amazon Prime: https://lmg.gg/8KV1v 55 | ►Audible Free Trial: https://lmg.gg/8242J 56 | ►Our Gear on Amazon: https://geni.us/OhmF 57 | 58 | FOLLOW US ELSEWHERE 59 | --------------------------------------------------- 60 | Twitter: https://twitter.com/linustech 61 | Facebook: http://www.facebook.com/LinusTech 62 | Instagram: https://www.instagram.com/linustech 63 | Twitch: https://www.twitch.tv/linustech 64 | 65 | FOLLOW OUR OTHER CHANNELS 66 | --------------------------------------------------- 67 | Mac Address: https://lmg.gg/macaddress 68 | Techquickie: https://lmg.gg/techquickieyt 69 | TechLinked: https://lmg.gg/techlinkedyt 70 | ShortCircuit: https://lmg.gg/shortcircuityt 71 | 72 | LMG Clips: https://lmg.gg/lmgclipsyt 73 | Channel Super Fun: https://lmg.gg/channelsuperfunyt 74 | Carpool Critics: https://lmg.gg/carpoolcriticsyt 75 | 76 | MUSIC CREDIT 77 | --------------------------------------------------- 78 | Title: Laszlo - Supernova 79 | Video Link: https://www.youtube.com/watch?v=PKfxmFU3lWY 80 | iTunes Download Link: https://itunes.apple.com/us/album/supernova/id936805712 81 | Artist Link: https://soundcloud.com/laszlomusic 82 | 83 | Outro Screen Music Credit: Approaching Nirvana - Sugar High http://www.youtube.com/approachingnirvana 84 | 85 | Intro animation by MBarek Abdelwassaa https://www.instagram.com/mbarek_abdel/ 86 | Monitor And Keyboard by vadimmihalkevich / CC BY 4.0 https://geni.us/PgGWp 87 | Mechanical RGB Keyboard by BigBrotherECE / CC BY 4.0 https://geni.us/mj6pHk4 88 | Mouse Gamer free Model By Oscar Creativo / CC BY 4.0 https://geni.us/Ps3XfE 89 | 90 | CHAPTERS 91 | --------------------------------------------------- 92 | 0:00 Intro 93 | 1:00 The Radeon RX 6600 XT 94 | 2:05 GPU pricing has been rising... 95 | 3:00 Thanks Ngreedia 96 | 4:12 Mo DRAM, mo problems 97 | 6:05 Raw deal on materials 98 | 7:09 Tariff Trump card 99 | 7:45 Shorted on silicon 100 | 9:03 Some good news for once... Sort of 101 | 9:45 The 6600 XT and the conclusion 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | yt:video:ZsSTR7fLpDg 110 | ZsSTR7fLpDg 111 | UCXuqSBlHAE6Xw-yeJA0Tunw 112 | This Motherboard Will Get You More Kills – Sh!t Manufacturers Say 113 | 114 | 115 | Linus Tech Tips 116 | https://www.youtube.com/channel/UCXuqSBlHAE6Xw-yeJA0Tunw 117 | 118 | 2021-07-28T17:01:44+00:00 119 | 2021-07-29T04:04:03+00:00 120 | 121 | This Motherboard Will Get You More Kills – Sh!t Manufacturers Say 122 | 123 | 124 | Use code LINUS to get 50% off a 2-year Nordpass Premium plan and get an additional 4 months for free at: https://www.nordpass.com/linus 125 | 126 | Get your Crucial X6 and X8 Portable SSDs here: http://crucial.gg/LinusTechTips 127 | 128 | We tested ASRock's lightning gaming ports to see if your high polling rate peripherals really need the extra help 129 | 130 | Buy ASRock Riptide X570 131 | On Newegg (PAID LINK): https://geni.us/9dK6mq8 132 | 133 | Buy SeaSonic Gold 750W PSU 134 | On Amazon (PAID LINK): https://geni.us/pL29c 135 | On Best Buy (PAID LINK): https://geni.us/nFJKob 136 | On Newegg (PAID LINK): https://geni.us/bTHu 137 | 138 | Buy Nvidia GTX 1070 GPU 139 | On Amazon (PAID LINK): https://geni.us/4LMwJoN 140 | On Best Buy (PAID LINK): https://geni.us/mJpAaUA 141 | On Newegg (PAID LINK): https://geni.us/nBo1lG 142 | 143 | Buy Cooler Master Hyper 212 Evo CPU Cooler 144 | On Amazon (PAID LINK): https://geni.us/9y2Zeu 145 | On Best Buy (PAID LINK): https://geni.us/lKEc1Nz 146 | On Newegg (PAID LINK): https://geni.us/Eg3Hz4 147 | 148 | Buy G.Skill 2x8GB 3200MHz RAM 149 | On Amazon (PAID LINK): https://geni.us/JCE58zu 150 | On Best Buy (PAID LINK): https://geni.us/yeqHF 151 | On Newegg (PAID LINK): https://geni.us/vtAi 152 | 153 | 154 | Purchases made through some store links may provide some compensation to Linus Media Group. 155 | 156 | Discuss on the forum: https://linustechtips.com/topic/1360353-this-motherboard-will-get-you-more-kills-%E2%80%93-sht-manufacturers-say/ 157 | 158 | 159 | ►GET MERCH: http://www.LTTStore.com/ 160 | ►SUPPORT US ON FLOATPLANE: https://www.floatplane.com/ 161 | ►LTX EXPO: https://www.ltxexpo.com/ 162 | 163 | AFFILIATES & REFERRALS 164 | --------------------------------------------------- 165 | ►Affiliates, Sponsors & Referrals: https://lmg.gg/sponsors 166 | ►Check out our podcast gear: https://kit.co/linustechtips/lmg-podcast-gear 167 | ►Private Internet Access VPN: https://lmg.gg/pialinus2 168 | ►Our Official Charging Partner Anker: https://lmg.gg/AnkerLTT 169 | ►MK Keyboards: https://lmg.gg/LyLtl 170 | ►Nerd or Die Stream Overlays: https://lmg.gg/avLlO 171 | ►Official Game Store: https://www.nexus.gg/ltt 172 | ►Amazon Prime: https://lmg.gg/8KV1v 173 | ►Audible Free Trial: https://lmg.gg/8242J 174 | ►Our Gear on Amazon: https://geni.us/OhmF 175 | 176 | FOLLOW US ELSEWHERE 177 | --------------------------------------------------- 178 | Twitter: https://twitter.com/linustech 179 | Facebook: http://www.facebook.com/LinusTech 180 | Instagram: https://www.instagram.com/linustech 181 | Twitch: https://www.twitch.tv/linustech 182 | 183 | FOLLOW OUR OTHER CHANNELS 184 | --------------------------------------------------- 185 | Mac Address: https://lmg.gg/macaddress 186 | Techquickie: https://lmg.gg/techquickieyt 187 | TechLinked: https://lmg.gg/techlinkedyt 188 | ShortCircuit: https://lmg.gg/shortcircuityt 189 | 190 | LMG Clips: https://lmg.gg/lmgclipsyt 191 | Channel Super Fun: https://lmg.gg/channelsuperfunyt 192 | Carpool Critics: https://lmg.gg/carpoolcriticsyt 193 | 194 | MUSIC CREDIT 195 | --------------------------------------------------- 196 | Title: Laszlo - Supernova 197 | Video Link: https://www.youtube.com/watch?v=PKfxmFU3lWY 198 | iTunes Download Link: https://itunes.apple.com/us/album/supernova/id936805712 199 | Artist Link: https://soundcloud.com/laszlomusic 200 | 201 | Outro Screen Music Credit: Approaching Nirvana - Sugar High http://www.youtube.com/approachingnirvana 202 | 203 | Intro animation by MBarek Abdelwassaa https://www.instagram.com/mbarek_abdel/ 204 | Monitor And Keyboard by vadimmihalkevich / CC BY 4.0 https://geni.us/PgGWp 205 | Mechanical RGB Keyboard by BigBrotherECE / CC BY 4.0 https://geni.us/mj6pHk4 206 | Mouse Gamer free Model By Oscar Creativo / CC BY 4.0 https://geni.us/Ps3XfE 207 | 208 | CHAPTERS 209 | --------------------------------------------------- 210 | 0:00 Intro 211 | 0:55 USB 3.0 212 | 1:48 High Polling Rates 213 | 2:40 USB Controller 214 | 3:20 Riptide 215 | 4:42 Results 216 | 5:15 Anthony Testing TIme 217 | 7:15 Conclusion 218 | 8:45 Outro 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | yt:video:qTrfMHaI3Dk 227 | qTrfMHaI3Dk 228 | UCXuqSBlHAE6Xw-yeJA0Tunw 229 | The $300 Holographic Photo Frame 230 | 231 | 232 | Linus Tech Tips 233 | https://www.youtube.com/channel/UCXuqSBlHAE6Xw-yeJA0Tunw 234 | 235 | 2021-07-27T17:00:31+00:00 236 | 2021-07-27T19:00:15+00:00 237 | 238 | The $300 Holographic Photo Frame 239 | 240 | 241 | Visit https://www.squarespace.com/LTT and use offer code LTT for 10% off 242 | 243 | Buy a Seasonic Ultra Titanium Power Supply: 244 | On Amazon: https://geni.us/q4lnefC 245 | On NewEgg: https://lmg.gg/8KV3S 246 | 247 | Using some fancy lenses the Looking Glass Portrait is able to create 3D images like we're never seen before in a consumer device. 248 | 249 | Buy Looking Glass Portrait 250 | https://geni.us/LookingGlass 251 | 252 | Purchases made through some store links may provide some compensation to Linus Media Group. 253 | 254 | Discuss on the forum: https://linustechtips.com/topic/1360095-the-300-holographic-photo-frame-looking-glass-portrait/ 255 | 256 | 257 | ►GET MERCH: http://www.LTTStore.com/ 258 | ►SUPPORT US ON FLOATPLANE: https://www.floatplane.com/ 259 | ►LTX EXPO: https://www.ltxexpo.com/ 260 | 261 | AFFILIATES & REFERRALS 262 | --------------------------------------------------- 263 | ►Affiliates, Sponsors & Referrals: https://lmg.gg/sponsors 264 | ►Check out our podcast gear: https://kit.co/linustechtips/lmg-podcast-gear 265 | ►Private Internet Access VPN: https://lmg.gg/pialinus2 266 | ►Our Official Charging Partner Anker: https://lmg.gg/AnkerLTT 267 | ►MK Keyboards: https://lmg.gg/LyLtl 268 | ►Nerd or Die Stream Overlays: https://lmg.gg/avLlO 269 | ►Official Game Store: https://www.nexus.gg/ltt 270 | ►Amazon Prime: https://lmg.gg/8KV1v 271 | ►Audible Free Trial: https://lmg.gg/8242J 272 | ►Our Gear on Amazon: https://geni.us/OhmF 273 | 274 | FOLLOW US ELSEWHERE 275 | --------------------------------------------------- 276 | Twitter: https://twitter.com/linustech 277 | Facebook: http://www.facebook.com/LinusTech 278 | Instagram: https://www.instagram.com/linustech 279 | Twitch: https://www.twitch.tv/linustech 280 | 281 | FOLLOW OUR OTHER CHANNELS 282 | --------------------------------------------------- 283 | Mac Address: https://lmg.gg/macaddress 284 | Techquickie: https://lmg.gg/techquickieyt 285 | TechLinked: https://lmg.gg/techlinkedyt 286 | ShortCircuit: https://lmg.gg/shortcircuityt 287 | 288 | LMG Clips: https://lmg.gg/lmgclipsyt 289 | Channel Super Fun: https://lmg.gg/channelsuperfunyt 290 | Carpool Critics: https://lmg.gg/carpoolcriticsyt 291 | 292 | MUSIC CREDIT 293 | --------------------------------------------------- 294 | Title: Laszlo - Supernova 295 | Video Link: https://www.youtube.com/watch?v=PKfxmFU3lWY 296 | iTunes Download Link: https://itunes.apple.com/us/album/supernova/id936805712 297 | Artist Link: https://soundcloud.com/laszlomusic 298 | 299 | Outro Screen Music Credit: Approaching Nirvana - Sugar High http://www.youtube.com/approachingnirvana 300 | 301 | Intro animation by MBarek Abdelwassaa https://www.instagram.com/mbarek_abdel/ 302 | Monitor And Keyboard by vadimmihalkevich / CC BY 4.0 https://geni.us/PgGWp 303 | Mechanical RGB Keyboard by BigBrotherECE / CC BY 4.0 https://geni.us/mj6pHk4 304 | Mouse Gamer free Model By Oscar Creativo / CC BY 4.0 https://geni.us/Ps3XfE 305 | 306 | CHAPTERS 307 | --------------------------------------------------- 308 | 0:00 Intro 309 | 1:45 The Portrait 310 | 3:23 How it works 311 | 4:20 Software 312 | 6:26 Opening it up 313 | 9:28 Who's this for? 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | yt:video:0rkTgPt3M4k 322 | 0rkTgPt3M4k 323 | UCXuqSBlHAE6Xw-yeJA0Tunw 324 | A COMPLETELY Upgradeable Laptop? 325 | 326 | 327 | Linus Tech Tips 328 | https://www.youtube.com/channel/UCXuqSBlHAE6Xw-yeJA0Tunw 329 | 330 | 2021-07-26T17:11:13+00:00 331 | 2021-07-28T02:24:22+00:00 332 | 333 | A COMPLETELY Upgradeable Laptop? 334 | 335 | 336 | Get a Free Pair of Wireless Bluetooth Headphones at Micro Center: https://micro.center/7f7633 337 | Check out the Micro Center Custom Builds Showcase: https://micro.center/792de5 338 | 339 | Get your G.Skill Z5i mini-ITX case today at: https://lmg.gg/Z5i 340 | 341 | When Framework told me they were making a completely repairable laptop I assumed it would be a flimsy chonker... I've never been so happy to be wrong. 342 | 343 | Check out Framework: https://frame.work/ 344 | 345 | Discuss on the forum: https://linustechtips.com/topic/1359778-a-completely-upgradeable-laptop/ 346 | 347 | 348 | ►GET MERCH: http://www.LTTStore.com/ 349 | ►SUPPORT US ON FLOATPLANE: https://www.floatplane.com/ 350 | ►LTX EXPO: https://www.ltxexpo.com/ 351 | 352 | AFFILIATES & REFERRALS 353 | --------------------------------------------------- 354 | ►Affiliates, Sponsors & Referrals: https://lmg.gg/sponsors 355 | ►Check out our podcast gear: https://kit.co/linustechtips/lmg-podcast-gear 356 | ►Private Internet Access VPN: https://lmg.gg/pialinus2 357 | ►Our Official Charging Partner Anker: https://lmg.gg/AnkerLTT 358 | ►MK Keyboards: https://lmg.gg/LyLtl 359 | ►Nerd or Die Stream Overlays: https://lmg.gg/avLlO 360 | ►Official Game Store: https://www.nexus.gg/ltt 361 | ►Amazon Prime: https://lmg.gg/8KV1v 362 | ►Audible Free Trial: https://lmg.gg/8242J 363 | ►Our Gear on Amazon: https://geni.us/OhmF 364 | 365 | FOLLOW US ELSEWHERE 366 | --------------------------------------------------- 367 | Twitter: https://twitter.com/linustech 368 | Facebook: http://www.facebook.com/LinusTech 369 | Instagram: https://www.instagram.com/linustech 370 | Twitch: https://www.twitch.tv/linustech 371 | 372 | FOLLOW OUR OTHER CHANNELS 373 | --------------------------------------------------- 374 | Mac Address: https://lmg.gg/macaddress 375 | Techquickie: https://lmg.gg/techquickieyt 376 | TechLinked: https://lmg.gg/techlinkedyt 377 | ShortCircuit: https://lmg.gg/shortcircuityt 378 | 379 | LMG Clips: https://lmg.gg/lmgclipsyt 380 | Channel Super Fun: https://lmg.gg/channelsuperfunyt 381 | Carpool Critics: https://lmg.gg/carpoolcriticsyt 382 | 383 | MUSIC CREDIT 384 | --------------------------------------------------- 385 | Title: Laszlo - Supernova 386 | Video Link: https://www.youtube.com/watch?v=PKfxmFU3lWY 387 | iTunes Download Link: https://itunes.apple.com/us/album/supernova/id936805712 388 | Artist Link: https://soundcloud.com/laszlomusic 389 | 390 | Outro Screen Music Credit: Approaching Nirvana - Sugar High http://www.youtube.com/approachingnirvana 391 | 392 | Intro animation by MBarek Abdelwassaa https://www.instagram.com/mbarek_abdel/ 393 | Monitor And Keyboard by vadimmihalkevich / CC BY 4.0 https://geni.us/PgGWp 394 | Mechanical RGB Keyboard by BigBrotherECE / CC BY 4.0 https://geni.us/mj6pHk4 395 | Mouse Gamer free Model By Oscar Creativo / CC BY 4.0 https://geni.us/Ps3XfE 396 | 397 | CHAPTERS 398 | --------------------------------------------------- 399 | 0:00 - You can't repair a MacBook! 400 | 0:15 - But you should be able to 401 | 0:42 - G.Skill 402 | 0:57 - Intro 403 | 1:06 - How Framework Started 404 | 2:28 - Opening it up 405 | 5:10 - Modular IO 406 | 8:30 - Motherboard 407 | 11:45 - Keyboard, trackpad, screen 408 | 14:20 - Setup and using it 409 | 17:50 - Micro Center 410 | 18:28 - Outro 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | yt:video:PJHIZa7tMl4 419 | PJHIZa7tMl4 420 | UCXuqSBlHAE6Xw-yeJA0Tunw 421 | Easy Small Form Factor Build? No. 422 | 423 | 424 | Linus Tech Tips 425 | https://www.youtube.com/channel/UCXuqSBlHAE6Xw-yeJA0Tunw 426 | 427 | 2021-07-25T17:23:32+00:00 428 | 2021-07-30T00:59:35+00:00 429 | 430 | Easy Small Form Factor Build? No. 431 | 432 | 433 | Check out the Drop + Captain America Custom Keycap Set at https://dro.ps/ltt-captamerica 434 | 435 | Save 10% and Free Worldwide Shipping at Ridge Wallet by using offer code LINUS at https://www.ridge.com/LINUS 436 | 437 | We went into this hoping the Jack of all Trades Small Form Factor, or JOAT SFF, would finally bring us a simple SFF build. Hoping. 438 | 439 | Check out the JOAT: https://spylabs.bigcartel.com/product/joatsff 440 | 441 | Discuss on the forum: https://linustechtips.com/topic/1359481-easy-small-form-factor-build-no/ 442 | 443 | 444 | ►GET MERCH: http://www.LTTStore.com/ 445 | ►SUPPORT US ON FLOATPLANE: https://www.floatplane.com/ 446 | ►LTX EXPO: https://www.ltxexpo.com/ 447 | 448 | AFFILIATES & REFERRALS 449 | --------------------------------------------------- 450 | ►Affiliates, Sponsors & Referrals: https://lmg.gg/sponsors 451 | ►Check out our podcast gear: https://kit.co/linustechtips/lmg-podcast-gear 452 | ►Private Internet Access VPN: https://lmg.gg/pialinus2 453 | ►Our Official Charging Partner Anker: https://lmg.gg/AnkerLTT 454 | ►MK Keyboards: https://lmg.gg/LyLtl 455 | ►Nerd or Die Stream Overlays: https://lmg.gg/avLlO 456 | ►Official Game Store: https://www.nexus.gg/ltt 457 | ►Amazon Prime: https://lmg.gg/8KV1v 458 | ►Audible Free Trial: https://lmg.gg/8242J 459 | ►Our Gear on Amazon: https://geni.us/OhmF 460 | 461 | FOLLOW US ELSEWHERE 462 | --------------------------------------------------- 463 | Twitter: https://twitter.com/linustech 464 | Facebook: http://www.facebook.com/LinusTech 465 | Instagram: https://www.instagram.com/linustech 466 | Twitch: https://www.twitch.tv/linustech 467 | 468 | FOLLOW OUR OTHER CHANNELS 469 | --------------------------------------------------- 470 | Mac Address: https://lmg.gg/macaddress 471 | Techquickie: https://lmg.gg/techquickieyt 472 | TechLinked: https://lmg.gg/techlinkedyt 473 | ShortCircuit: https://lmg.gg/shortcircuityt 474 | 475 | LMG Clips: https://lmg.gg/lmgclipsyt 476 | Channel Super Fun: https://lmg.gg/channelsuperfunyt 477 | Carpool Critics: https://lmg.gg/carpoolcriticsyt 478 | 479 | MUSIC CREDIT 480 | --------------------------------------------------- 481 | Title: Laszlo - Supernova 482 | Video Link: https://www.youtube.com/watch?v=PKfxmFU3lWY 483 | iTunes Download Link: https://itunes.apple.com/us/album/supernova/id936805712 484 | Artist Link: https://soundcloud.com/laszlomusic 485 | 486 | Outro Screen Music Credit: Approaching Nirvana - Sugar High http://www.youtube.com/approachingnirvana 487 | 488 | Intro animation by MBarek Abdelwassaa https://www.instagram.com/mbarek_abdel/ 489 | Monitor And Keyboard by vadimmihalkevich / CC BY 4.0 https://geni.us/PgGWp 490 | Mechanical RGB Keyboard by BigBrotherECE / CC BY 4.0 https://geni.us/mj6pHk4 491 | Mouse Gamer free Model By Oscar Creativo / CC BY 4.0 https://geni.us/Ps3XfE 492 | 493 | CHAPTERS 494 | --------------------------------------------------- 495 | 0:00 - SFF is hard 496 | 0:20 - But is it?? 497 | 0:40 - Ridge Wallet 498 | 0:52 - Intro 499 | 1:01 - The Spylabs JOAT (Jack of all Trades) 500 | 1:48 - Case Assembly 501 | 2:42 - Sketchy Power Cable 502 | 4:10 - Case Assembly, but it fights back 503 | 5:50 - PSU 504 | 8:03 - Linus building a computer 505 | 11:40 - Will the NH-P1 fit? 506 | 12:22 - The NH-P1 will not fit. 507 | 13:00 - NH-D15 is a good one 508 | 14:20 - The pain is over, if it boots 509 | 15:30 - It's friggin' awesome! 510 | 17:55 - Drop.com 511 | 18:33 - Outro 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | yt:video:SypkW1g4jMc 520 | SypkW1g4jMc 521 | UCXuqSBlHAE6Xw-yeJA0Tunw 522 | Techifying a freakin' BOAT! 523 | 524 | 525 | Linus Tech Tips 526 | https://www.youtube.com/channel/UCXuqSBlHAE6Xw-yeJA0Tunw 527 | 528 | 2021-07-24T17:00:26+00:00 529 | 2021-07-24T17:26:54+00:00 530 | 531 | Techifying a freakin' BOAT! 532 | 533 | 534 | Thanks to Jackery for sponsoring today's video! Get 10% off all Jackery products on their website with code LinusTechTips: https://www.jackery.com?aff=27 535 | 536 | We overhauled a boat with the latest in tech featuring Jackery's Explorer 2000 Solar generator! 537 | 538 | Buy Apple TV 4K 2021 539 | On Amazon (PAID LINK): https://geni.us/DF4JWpJ 540 | On Best Buy (PAID LINK): https://geni.us/bGuXN 541 | On B&H (PAID LINK): https://geni.us/sZx0A 542 | 543 | Buy Apple iPad Pro 544 | On Amazon (PAID LINK): https://geni.us/dYqp 545 | On Best Buy (PAID LINK): https://geni.us/LUoq3d 546 | On Newegg (PAID LINK): https://geni.us/GsJN 547 | 548 | Buy RAM Mounts 549 | On Amazon (PAID LINK): https://geni.us/e39lh 550 | On B&H (PAID LINK): https://geni.us/S61HC4 551 | 552 | Buy Samsung Monitors 553 | On Amazon (PAID LINK): https://geni.us/OnBf 554 | On Best Buy (PAID LINK): https://geni.us/0kbvZ 555 | On Newegg (PAID LINK): https://geni.us/BAONZa 556 | 557 | Buy Kanto RV250G TV Wall Mount 558 | On Amazon (PAID LINK): https://geni.us/BfWvSax 559 | On Newegg (PAID LINK): https://geni.us/JaLWCT 560 | On B&H (PAID LINK): https://geni.us/YiWWwJ 561 | 562 | Buy Polk Audio Atrium5 Outdoor Speakers 563 | On Amazon (PAID LINK): https://geni.us/zjg0ZlA 564 | On Newegg (PAID LINK): https://geni.us/qnKjJq 565 | On B&H (PAID LINK): https://geni.us/IQA3y1k 566 | 567 | Buy Alpine Electronics PWE-S8 Subwoofer 568 | On Amazon (PAID LINK): https://geni.us/VvjG 569 | On Best Buy (PAID LINK): https://geni.us/ObAlH8 570 | On Newegg (PAID LINK): https://geni.us/wQAAD 571 | 572 | Buy JL Audio C1-400 Car Audio Speakers 573 | On Amazon (PAID LINK): https://geni.us/5sjRu 574 | On Newegg (PAID LINK): https://geni.us/dc0bG 575 | 576 | Purchases made through some store links may provide some compensation to Linus Media Group. 577 | 578 | Discuss on the forum: https://linustechtips.com/topic/1359246-techifying-a-freakin-boat/ 579 | 580 | ►GET MERCH: http://www.LTTStore.com/ 581 | ►SUPPORT US ON FLOATPLANE: https://www.floatplane.com/ 582 | ►LTX EXPO: https://www.ltxexpo.com/ 583 | 584 | AFFILIATES & REFERRALS 585 | --------------------------------------------------- 586 | ►Affiliates, Sponsors & Referrals: https://lmg.gg/sponsors 587 | ►Check out our podcast gear: https://kit.co/linustechtips/lmg-podcast-gear 588 | ►Private Internet Access VPN: https://lmg.gg/pialinus2 589 | ►Our Official Charging Partner Anker: https://lmg.gg/AnkerLTT 590 | ►MK Keyboards: https://lmg.gg/LyLtl 591 | ►Nerd or Die Stream Overlays: https://lmg.gg/avLlO 592 | ►Official Game Store: https://www.nexus.gg/ltt 593 | ►Amazon Prime: https://lmg.gg/8KV1v 594 | ►Audible Free Trial: https://lmg.gg/8242J 595 | ►Our Gear on Amazon: https://geni.us/OhmF 596 | 597 | FOLLOW US ELSEWHERE 598 | --------------------------------------------------- 599 | Twitter: https://twitter.com/linustech 600 | Facebook: http://www.facebook.com/LinusTech 601 | Instagram: https://www.instagram.com/linustech 602 | Twitch: https://www.twitch.tv/linustech 603 | 604 | FOLLOW OUR OTHER CHANNELS 605 | --------------------------------------------------- 606 | Mac Address: https://lmg.gg/macaddress 607 | Techquickie: https://lmg.gg/techquickieyt 608 | TechLinked: https://lmg.gg/techlinkedyt 609 | ShortCircuit: https://lmg.gg/shortcircuityt 610 | 611 | LMG Clips: https://lmg.gg/lmgclipsyt 612 | Channel Super Fun: https://lmg.gg/channelsuperfunyt 613 | Carpool Critics: https://lmg.gg/carpoolcriticsyt 614 | 615 | MUSIC CREDIT 616 | --------------------------------------------------- 617 | Title: Laszlo - Supernova 618 | Video Link: https://www.youtube.com/watch?v=PKfxmFU3lWY 619 | iTunes Download Link: https://itunes.apple.com/us/album/supernova/id936805712 620 | Artist Link: https://soundcloud.com/laszlomusic 621 | 622 | Outro Screen Music Credit: Approaching Nirvana - Sugar High http://www.youtube.com/approachingnirvana 623 | 624 | Intro animation by MBarek Abdelwassaa https://www.instagram.com/mbarek_abdel/ 625 | Monitor And Keyboard by vadimmihalkevich / CC BY 4.0 https://geni.us/PgGWp 626 | Mechanical RGB Keyboard by BigBrotherECE / CC BY 4.0 https://geni.us/mj6pHk4 627 | Mouse Gamer free Model By Oscar Creativo / CC BY 4.0 https://geni.us/Ps3XfE 628 | 629 | CHAPTERS 630 | --------------------------------------------------- 631 | 0:00 Don't hit the boat, Linus! 632 | 0:39 Entertainment system setup 633 | 2:54 Cable-managing a boat is hard lol 634 | 3:38 VESA Mounting issues 635 | 5:01 Story behind Colin's Dad's boat 636 | 6:08 Wiring done but diagnosing power switch 637 | 6:25 Outdoor speaker install 638 | 7:51 Subwoofer mounting time 639 | 8:23 Jackery Saga Solar Generator install and Crabrave 640 | 10:09 The tech side of things 641 | 11:03 Conclusion and Jackery Explorer 2000 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | yt:video:2xlkKIGNsMw 650 | 2xlkKIGNsMw 651 | UCXuqSBlHAE6Xw-yeJA0Tunw 652 | Talk me Down from The Wall... - WAN Show July 23, 2021 653 | 654 | 655 | Linus Tech Tips 656 | https://www.youtube.com/channel/UCXuqSBlHAE6Xw-yeJA0Tunw 657 | 658 | 2021-07-24T03:09:41+00:00 659 | 2021-07-27T19:37:27+00:00 660 | 661 | Talk me Down from The Wall... - WAN Show July 23, 2021 662 | 663 | 664 | Pre-order Megapro's new 24-in-1 Precision Screwdriver at https://lmg.gg/MegaproWAN 665 | 666 | Start your build today at https://www.buildredux.com/linus 667 | 668 | Try FreshBooks free, for 30 days, no credit card required at https://www.freshbooks.com/wan 669 | 670 | Podcast Download: https://anchor.fm/thewanshowpodcast/episodes/Talk-me-Down-from-The-Wall------WAN-Show-July-23--2021-e151loa 671 | 672 | Check out our other Podcasts: 673 | Carpool Critics Movie Podcast: https://www.youtube.com/channel/UCt-oJR5teQIjOAxCmIQvcgA 674 | 675 | Timestamps (Courtacy of NoKi1119) 676 | [0:00] Chapters 677 | [1:39] Intro 678 | [2:40] Topic #1: Blizzard civil lawsuit. 679 | 4:24 Discrimination and sexual conduct. 680 | 5:34 Activision's response to the allegations. 681 | 6:16 Harassment towards female workers. 682 | 9:17 Discussing the response. 683 | [18:47] Topic #2: Samsung's second generation 'The Wall'. 684 | 19:37 Specifications of the new display. 685 | 20:29 Advantages of MicroLED. 686 | 21:29 Wattage and required cooling. 687 | 35:42 Possible content using the display. 688 | 44:05 Golden controller being sold. 689 | 46:34 Sony projectors and others as a substitute. 690 | [54:52] Sponsors 691 | 55:31 Megapro's Screwdriver. 692 | 56:22 Freshbooks Accounting. 693 | 57:34 Redux PC Builder. 694 | [58:38] New LTTstore merch. 695 | [1:02:48] Topic #3: 30% decrease in WoW players during the pandemic. 696 | 1:03:06 Reasons behind the decrease. 697 | [1:03:56] Topic #3.5: Amazon's MMO "New World" bricks RTX 3090's. 698 | [1:08:20] Topic #4: Spectrum Eve monitor. 699 | 1:10:01 Poll: To cover or not to cover? 700 | 1:12:45 Reasons behind the interest. 701 | [1:13:18] Topic #5: 'Freedom Phone'. 702 | 1:13:46 Discussing Finman's claims. 703 | 1:16:03 FP is a more expensive UMIDIGI phone. 704 | [1:19:34] Topic #6: Bezos brothers went to space. 705 | 1:21:27 Jeff thanking Amazon employees and customers for this. 706 | [1:23:46] Topic #7: Nvidia's MediaTek ARM CPU demo. 707 | 1:25:58 Scientist patched Linux on RISC-V CPU with RX 6700 XT. 708 | 1:27:38 Intel's (leaked) 12th generation is in 10nm. 709 | [1:28:07] Superchats (& Impersonating Jeff Bezos) 710 | [1:46:44] Wrapping up 711 | [1:47:13] Outro 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | yt:video:_Ua-d9OeUOg 720 | _Ua-d9OeUOg 721 | UCXuqSBlHAE6Xw-yeJA0Tunw 722 | How to install Linux instead of Windows 11 723 | 724 | 725 | Linus Tech Tips 726 | https://www.youtube.com/channel/UCXuqSBlHAE6Xw-yeJA0Tunw 727 | 728 | 2021-07-22T17:00:00+00:00 729 | 2021-07-24T13:51:52+00:00 730 | 731 | How to install Linux instead of Windows 11 732 | 733 | 734 | Join us in War Thunder for FREE at https://playwt.link/JoinLinusTechTips Get an exclusive bonus using our link - thanks for supporting the channel! 735 | 736 | Windows 11 is about to make a lot of people feel left behind, but there’s one operating system that’s recently been getting better and better for new and old hardware… 737 | 738 | Check out Pop!_OS: https://pop.system76.com/ 739 | Grab BalenaEtcher: https://www.balena.io/etcher/ 740 | Grab Rufus: https://rufus.ie/en/ 741 | Get nvidia-patch: https://github.com/keylase/nvidia-patch 742 | Get obs-nvfbc: https://gitlab.com/fzwoch/obs-nvfbc 743 | 744 | Buy ASUS ROG Swift PG329Q 32” Gaming Monitor 745 | On Amazon (PAID LINK): https://geni.us/Azr3Czm 746 | On Newegg (PAID LINK): https://geni.us/AlUrM 747 | On B&H (PAID LINK): https://geni.us/PGiu9n 748 | 749 | Discuss on the forum: https://linustechtips.com/topic/1358499-how-to-install-linux-instead-of-windows-11/ 750 | 751 | 752 | ►GET MERCH: http://www.LTTStore.com/ 753 | ►SUPPORT US ON FLOATPLANE: https://www.floatplane.com/ 754 | ►LTX EXPO: https://www.ltxexpo.com/ 755 | 756 | AFFILIATES & REFERRALS 757 | --------------------------------------------------- 758 | ►Affiliates, Sponsors & Referrals: https://lmg.gg/sponsors 759 | ►Check out our podcast gear: https://kit.co/linustechtips/lmg-podcast-gear 760 | ►Private Internet Access VPN: https://lmg.gg/pialinus2 761 | ►Our Official Charging Partner Anker: https://lmg.gg/AnkerLTT 762 | ►MK Keyboards: https://lmg.gg/LyLtl 763 | ►Nerd or Die Stream Overlays: https://lmg.gg/avLlO 764 | ►Official Game Store: https://www.nexus.gg/ltt 765 | ►Amazon Prime: https://lmg.gg/8KV1v 766 | ►Audible Free Trial: https://lmg.gg/8242J 767 | ►Our Gear on Amazon: https://geni.us/OhmF 768 | 769 | FOLLOW US ELSEWHERE 770 | --------------------------------------------------- 771 | Twitter: https://twitter.com/linustech 772 | Facebook: http://www.facebook.com/LinusTech 773 | Instagram: https://www.instagram.com/linustech 774 | Twitch: https://www.twitch.tv/linustech 775 | 776 | FOLLOW OUR OTHER CHANNELS 777 | --------------------------------------------------- 778 | Mac Address: https://lmg.gg/macaddress 779 | Techquickie: https://lmg.gg/techquickieyt 780 | TechLinked: https://lmg.gg/techlinkedyt 781 | ShortCircuit: https://lmg.gg/shortcircuityt 782 | 783 | LMG Clips: https://lmg.gg/lmgclipsyt 784 | Channel Super Fun: https://lmg.gg/channelsuperfunyt 785 | Carpool Critics: https://lmg.gg/carpoolcriticsyt 786 | 787 | MUSIC CREDIT 788 | --------------------------------------------------- 789 | Title: Laszlo - Supernova 790 | Video Link: https://www.youtube.com/watch?v=PKfxmFU3lWY 791 | iTunes Download Link: https://itunes.apple.com/us/album/supernova/id936805712 792 | Artist Link: https://soundcloud.com/laszlomusic 793 | 794 | Outro Screen Music Credit: Approaching Nirvana - Sugar High http://www.youtube.com/approachingnirvana 795 | 796 | Intro animation by MBarek Abdelwassaa https://www.instagram.com/mbarek_abdel/ 797 | Monitor And Keyboard by vadimmihalkevich / CC BY 4.0 https://geni.us/PgGWp 798 | Mechanical RGB Keyboard by BigBrotherECE / CC BY 4.0 https://geni.us/mj6pHk4 799 | Mouse Gamer free Model By Oscar Creativo / CC BY 4.0 https://geni.us/Ps3XfE 800 | 801 | CHAPTERS 802 | --------------------------------------------------- 803 | 0:00 Intro 804 | 0:55 What is Linux and why should I care? 805 | 2:21 Getting Pop!_OS 806 | 4:03 Booting & the installer 807 | 6:20 Post-install setup & downloading apps 808 | 8:14 Installing Wine (optional) 809 | 8:55 Installing games 810 | 9:38 A Shadowplay alternative (optional) 811 | 11:56 Compatibility, drivers, & caveats 812 | 13:37 Conclusion & why I won't force you 813 | 814 | 815 | 816 | 817 | 818 | 819 | 820 | yt:video:SKtEH_7lGJg 821 | SKtEH_7lGJg 822 | UCXuqSBlHAE6Xw-yeJA0Tunw 823 | NVIDIA Thinks These GPUs Are Worthless 824 | 825 | 826 | Linus Tech Tips 827 | https://www.youtube.com/channel/UCXuqSBlHAE6Xw-yeJA0Tunw 828 | 829 | 2021-07-21T17:09:32+00:00 830 | 2021-07-26T14:31:19+00:00 831 | 832 | NVIDIA Thinks These GPUs Are Worthless 833 | 834 | 835 | Thanks to Morning Brew for sponsoring today's video! Sign up to Morning Brew for free today at http://bit.ly/mblinustech 836 | 837 | Save 10% and Free Worldwide Shipping at Ridge Wallet by using offer code LINUS at https://www.ridge.com/LINUS 838 | 839 | Recently NVIDIA announced that they would be discontinuing Game Ready driver support for their Kepler architecture-based GPUs like the 600 and 700 series. Does this mean these GPUs can no longer game? Today we find out. 840 | 841 | Buy an NVIDIA GPU 842 | On Amazon (PAID LINK): https://geni.us/cwCc 843 | On Best Buy (PAID LINK): https://geni.us/hEfP 844 | On Newegg (PAID LINK): https://geni.us/Fhed 845 | 846 | Buy an AMD GPU 847 | On Amazon (PAID LINK): https://geni.us/eYdbdG 848 | On Best Buy (PAID LINK): https://geni.us/IcvWziv 849 | On Newegg (PAID LINK): https://geni.us/sUb5w4U 850 | 851 | Purchases made through some store links may provide some compensation to Linus Media Group. 852 | 853 | Discuss on the forum: https://linustechtips.com/topic/1358410-nvidia-thinks-these-are-worthless/ 854 | 855 | 856 | ►GET MERCH: http://www.LTTStore.com/ 857 | ►SUPPORT US ON FLOATPLANE: https://www.floatplane.com/ 858 | ►LTX EXPO: https://www.ltxexpo.com/ 859 | 860 | AFFILIATES & REFERRALS 861 | --------------------------------------------------- 862 | ►Affiliates, Sponsors & Referrals: https://lmg.gg/sponsors 863 | ►Check out our podcast gear: https://kit.co/linustechtips/lmg-podcast-gear 864 | ►Private Internet Access VPN: https://lmg.gg/pialinus2 865 | ►Our Official Charging Partner Anker: https://lmg.gg/AnkerLTT 866 | ►MK Keyboards: https://lmg.gg/LyLtl 867 | ►Nerd or Die Stream Overlays: https://lmg.gg/avLlO 868 | ►Official Game Store: https://www.nexus.gg/ltt 869 | ►Amazon Prime: https://lmg.gg/8KV1v 870 | ►Audible Free Trial: https://lmg.gg/8242J 871 | ►Our Gear on Amazon: https://geni.us/OhmF 872 | 873 | FOLLOW US ELSEWHERE 874 | --------------------------------------------------- 875 | Twitter: https://twitter.com/linustech 876 | Facebook: http://www.facebook.com/LinusTech 877 | Instagram: https://www.instagram.com/linustech 878 | Twitch: https://www.twitch.tv/linustech 879 | 880 | FOLLOW OUR OTHER CHANNELS 881 | --------------------------------------------------- 882 | Mac Address: https://lmg.gg/macaddress 883 | Techquickie: https://lmg.gg/techquickieyt 884 | TechLinked: https://lmg.gg/techlinkedyt 885 | ShortCircuit: https://lmg.gg/shortcircuityt 886 | 887 | LMG Clips: https://lmg.gg/lmgclipsyt 888 | Channel Super Fun: https://lmg.gg/channelsuperfunyt 889 | Carpool Critics: https://lmg.gg/carpoolcriticsyt 890 | 891 | MUSIC CREDIT 892 | --------------------------------------------------- 893 | Title: Laszlo - Supernova 894 | Video Link: https://www.youtube.com/watch?v=PKfxmFU3lWY 895 | iTunes Download Link: https://itunes.apple.com/us/album/supernova/id936805712 896 | Artist Link: https://soundcloud.com/laszlomusic 897 | 898 | Outro Screen Music Credit: Approaching Nirvana - Sugar High http://www.youtube.com/approachingnirvana 899 | 900 | Monitor And Keyboard by vadimmihalkevich / CC BY 4.0 https://geni.us/PgGWp 901 | Mechanical RGB Keyboard by BigBrotherECE / CC BY 4.0 https://geni.us/mj6pHk4 902 | Mouse Gamer free Model By Oscar Creativo / CC BY 4.0 https://geni.us/Ps3XfE 903 | 904 | CHAPTERS 905 | --------------------------------------------------- 906 | 0:00 Intro 907 | 1:21 Introducing the GTX 760 908 | 3:12 760 - CSGO 909 | 4:02 760 - Rocket League 910 | 4:42 760 - F1 2020 911 | 5:02 760 - Apex Legends 912 | 6:21 760 - Doom Eternal & VRAM Discussion 913 | 8:00 Introducing the GTX 780 Ti 914 | 8:50 780 Ti - F1 2020 915 | 9:36 780 Ti - Doom Eternal 916 | 10:25 780 Ti - Dirt 5 & DirectX 12 Discussion 917 | 11:25 780 Ti - Civilization VI 918 | 12:05 780 Ti - Control 919 | 12:23 Why Discontinuing These Cards Might Make Sense 920 | 15:45 What If You Already Have a Kepler-Based GPU? 921 | 16:28 Outro 922 | 923 | 924 | 925 | 926 | 927 | 928 | 929 | yt:video:fqpSbdkjBEg 930 | fqpSbdkjBEg 931 | UCXuqSBlHAE6Xw-yeJA0Tunw 932 | I bought this $9000 CPU for $999 😁 933 | 934 | 935 | Linus Tech Tips 936 | https://www.youtube.com/channel/UCXuqSBlHAE6Xw-yeJA0Tunw 937 | 938 | 2021-07-20T17:09:42+00:00 939 | 2021-07-20T17:27:10+00:00 940 | 941 | I bought this $9000 CPU for $999 😁 942 | 943 | 944 | Get a Free Pair of Wireless Bluetooth Headphones at Micro Center: https://micro.center/7f7633 945 | Check out the Micro Center Custom Builds Showcase: https://micro.center/792de5 946 | 947 | Buy a Seasonic Ultra Titanium Power Supply: 948 | On Amazon: https://geni.us/q4lnefC 949 | On NewEgg: https://lmg.gg/8KV3S 950 | 951 | Intel CPUs were at one point the go-to for nearly every market segment, with powerful products for gamers, datacenters, and content creators alike. AMD has dethroned them, and that’s led to some strangely cheap products popping up on Ebay… like this 28 core Xeon. 952 | 953 | Buy Intel Xeon Platinum 8176 CPU 954 | On eBay (PAID LINK): https://ebay.us/ANlWnf 955 | On Newegg (PAID LINK): https://geni.us/QiLhs 956 | 957 | Purchases made through some store links may provide some compensation to Linus Media Group. 958 | 959 | Discuss on the forum: https://linustechtips.com/topic/1358086-i-bought-this-9000-cpu-for-999-%F0%9F%98%81 960 | 961 | 962 | ►GET MERCH: http://www.LTTStore.com/ 963 | ►SUPPORT US ON FLOATPLANE: https://www.floatplane.com/ 964 | ►LTX EXPO: https://www.ltxexpo.com/ 965 | 966 | AFFILIATES & REFERRALS 967 | --------------------------------------------------- 968 | ►Affiliates, Sponsors & Referrals: https://lmg.gg/sponsors 969 | ►Check out our podcast gear: https://kit.co/linustechtips/lmg-podcast-gear 970 | ►Private Internet Access VPN: https://lmg.gg/pialinus2 971 | ►Our Official Charging Partner Anker: https://lmg.gg/AnkerLTT 972 | ►MK Keyboards: https://lmg.gg/LyLtl 973 | ►Nerd or Die Stream Overlays: https://lmg.gg/avLlO 974 | ►Official Game Store: https://www.nexus.gg/ltt 975 | ►Amazon Prime: https://lmg.gg/8KV1v 976 | ►Audible Free Trial: https://lmg.gg/8242J 977 | ►Our Gear on Amazon: https://geni.us/OhmF 978 | 979 | FOLLOW US ELSEWHERE 980 | --------------------------------------------------- 981 | Twitter: https://twitter.com/linustech 982 | Facebook: http://www.facebook.com/LinusTech 983 | Instagram: https://www.instagram.com/linustech 984 | Twitch: https://www.twitch.tv/linustech 985 | 986 | FOLLOW OUR OTHER CHANNELS 987 | --------------------------------------------------- 988 | Mac Address: https://lmg.gg/macaddress 989 | Techquickie: https://lmg.gg/techquickieyt 990 | TechLinked: https://lmg.gg/techlinkedyt 991 | ShortCircuit: https://lmg.gg/shortcircuityt 992 | 993 | LMG Clips: https://lmg.gg/lmgclipsyt 994 | Channel Super Fun: https://lmg.gg/channelsuperfunyt 995 | Carpool Critics: https://lmg.gg/carpoolcriticsyt 996 | 997 | MUSIC CREDIT 998 | --------------------------------------------------- 999 | Title: Laszlo - Supernova 1000 | Video Link: https://www.youtube.com/watch?v=PKfxmFU3lWY 1001 | iTunes Download Link: https://itunes.apple.com/us/album/supernova/id936805712 1002 | Artist Link: https://soundcloud.com/laszlomusic 1003 | 1004 | Outro Screen Music Credit: Approaching Nirvana - Sugar High http://www.youtube.com/approachingnirvana 1005 | 1006 | Monitor And Keyboard by vadimmihalkevich / CC BY 4.0 https://geni.us/PgGWp 1007 | Mechanical RGB Keyboard by BigBrotherECE / CC BY 4.0 https://geni.us/mj6pHk4 1008 | Mouse Gamer free Model By Oscar Creativo / CC BY 4.0 https://geni.us/Ps3XfE 1009 | 1010 | CHAPTERS 1011 | --------------------------------------------------- 1012 | 0:00 Intro 1013 | 0:55 Backstory 1014 | 1:42 The server hardware cycle 1015 | 2:46 Our CPU 1016 | 3:01 Server CPU "classes" 1017 | 5:18 Summary so far 1018 | 5:58 Installation begins 1019 | 6:08 C621 Motherboards 1020 | 6:37 Socket design and coolers 1021 | 7:20 gaming 1022 | 8:30 Clock speeds and per-core boosting 1023 | 9:08 Linus has a eureka 1024 | 10:04 What this CPU isn't good for 1025 | 10:43 What this CPU IS good for 1026 | 1027 | 1028 | 1029 | 1030 | 1031 | 1032 | 1033 | yt:video:JaD_Ze-544E 1034 | JaD_Ze-544E 1035 | UCXuqSBlHAE6Xw-yeJA0Tunw 1036 | This Laptop is ALL SCREEN! 1037 | 1038 | 1039 | Linus Tech Tips 1040 | https://www.youtube.com/channel/UCXuqSBlHAE6Xw-yeJA0Tunw 1041 | 1042 | 2021-07-19T17:20:07+00:00 1043 | 2021-07-20T15:55:34+00:00 1044 | 1045 | This Laptop is ALL SCREEN! 1046 | 1047 | 1048 | You can try your first month of KiwiCo for FREE at: http://kiwico.com/LTT 1049 | 1050 | Foldable devices are here, or more specifically, foldable displays. Laptops and notebooks fold to make things more portable, but what if we folded the display itself? 1051 | 1052 | Buy Lenovo ThinkPad X1 Fold 1053 | On Amazon (PAID LINK): https://geni.us/R6hc 1054 | On Best Buy (PAID LINK): https://geni.us/TwiqQC 1055 | On Newegg (PAID LINK): https://geni.us/yeMWnw 1056 | 1057 | Purchases made through some store links may provide some compensation to Linus Media Group. 1058 | 1059 | Discuss on the forum: https://linustechtips.com/topic/1357826-we-have-some-thoughts-about-folding-laptops/ 1060 | 1061 | ►GET MERCH: http://www.LTTStore.com/ 1062 | ►SUPPORT US ON FLOATPLANE: https://www.floatplane.com/ 1063 | ►LTX EXPO: https://www.ltxexpo.com/ 1064 | 1065 | AFFILIATES & REFERRALS 1066 | --------------------------------------------------- 1067 | ►Affiliates, Sponsors & Referrals: https://lmg.gg/sponsors 1068 | ►Check out our podcast gear: https://kit.co/linustechtips/lmg-podcast-gear 1069 | ►Private Internet Access VPN: https://lmg.gg/pialinus2 1070 | ►Our Official Charging Partner Anker: https://lmg.gg/AnkerLTT 1071 | ►MK Keyboards: https://lmg.gg/LyLtl 1072 | ►Nerd or Die Stream Overlays: https://lmg.gg/avLlO 1073 | ►Official Game Store: https://www.nexus.gg/ltt 1074 | ►Amazon Prime: https://lmg.gg/8KV1v 1075 | ►Audible Free Trial: https://lmg.gg/8242J 1076 | ►Our Gear on Amazon: https://geni.us/OhmF 1077 | 1078 | FOLLOW US ELSEWHERE 1079 | --------------------------------------------------- 1080 | Twitter: https://twitter.com/linustech 1081 | Facebook: http://www.facebook.com/LinusTech 1082 | Instagram: https://www.instagram.com/linustech 1083 | Twitch: https://www.twitch.tv/linustech 1084 | 1085 | FOLLOW OUR OTHER CHANNELS 1086 | --------------------------------------------------- 1087 | Mac Address: https://lmg.gg/macaddress 1088 | Techquickie: https://lmg.gg/techquickieyt 1089 | TechLinked: https://lmg.gg/techlinkedyt 1090 | ShortCircuit: https://lmg.gg/shortcircuityt 1091 | 1092 | LMG Clips: https://lmg.gg/lmgclipsyt 1093 | Channel Super Fun: https://lmg.gg/channelsuperfunyt 1094 | Carpool Critics: https://lmg.gg/carpoolcriticsyt 1095 | 1096 | MUSIC CREDIT 1097 | --------------------------------------------------- 1098 | Title: Laszlo - Supernova 1099 | Video Link: https://www.youtube.com/watch?v=PKfxmFU3lWY 1100 | iTunes Download Link: https://itunes.apple.com/us/album/supernova/id936805712 1101 | Artist Link: https://soundcloud.com/laszlomusic 1102 | 1103 | Outro Screen Music Credit: Approaching Nirvana - Sugar High http://www.youtube.com/approachingnirvana 1104 | 1105 | Monitor And Keyboard by vadimmihalkevich / CC BY 4.0 https://geni.us/PgGWp 1106 | Mechanical RGB Keyboard by BigBrotherECE / CC BY 4.0 https://geni.us/mj6pHk4 1107 | Mouse Gamer free Model By Oscar Creativo / CC BY 4.0 https://geni.us/Ps3XfE 1108 | 1109 | CHAPTERS 1110 | --------------------------------------------------- 1111 | 0:00 Intro 1112 | 0:52 The display 1113 | 1:27 The hinge 1114 | 1:49 Exterior design 1115 | 2:07 Optional stylus 1116 | 3:03 The Fold Keyboard 1117 | 3:21 Portability 1118 | 3:45 alex is taking things from other employees is anyone gonna stop him pls guys i need 1119 | 3:49 Is it ACTUALLY good as a laptop, though? 1120 | 4:20 A strange design decision 1121 | 4:33 Tech specs 1122 | 6:12 The price & value 1123 | 6:50 webcam 1124 | 7:00 Final thoughts 1125 | 1126 | 1127 | 1128 | 1129 | 1130 | 1131 | 1132 | yt:video:LXj5A9ZhPSE 1133 | LXj5A9ZhPSE 1134 | UCXuqSBlHAE6Xw-yeJA0Tunw 1135 | Where did these AWESOME Retro Consoles come from??? 1136 | 1137 | 1138 | Linus Tech Tips 1139 | https://www.youtube.com/channel/UCXuqSBlHAE6Xw-yeJA0Tunw 1140 | 1141 | 2021-07-18T17:00:02+00:00 1142 | 2021-07-18T20:06:13+00:00 1143 | 1144 | Where did these AWESOME Retro Consoles come from??? 1145 | 1146 | 1147 | Check out the Manta toolkit at: https://www.iFixit.com/LTT 1148 | 1149 | Every gaming handheld I’ve ever owned has come from some big Japanese company – But these didn’t. What are they, and can they possibly be any good? 1150 | 1151 | Buy ANBERNIC RG351M 1152 | On Amazon (PAID LINK): https://geni.us/wyoXuo 1153 | On Newegg (PAID LINK): https://geni.us/4vCfF0 1154 | 1155 | Buy Retroid Pocket 2 1156 | On Amazon (PAID LINK): https://geni.us/pNp8iqt 1157 | On Newegg (PAID LINK): https://geni.us/P0MBl0 1158 | 1159 | Check out the ODROID-GO Super at https://lmg.gg/QZpTN 1160 | 1161 | Purchases made through some store links may provide some compensation to Linus Media Group. 1162 | 1163 | Discuss on the forum: https://linustechtips.com/topic/1357425-where-did-these-come-from/ 1164 | 1165 | 1166 | ►GET MERCH: http://www.LTTStore.com/ 1167 | ►SUPPORT US ON FLOATPLANE: https://www.floatplane.com/ 1168 | ►LTX EXPO: https://www.ltxexpo.com/ 1169 | 1170 | AFFILIATES & REFERRALS 1171 | --------------------------------------------------- 1172 | ►Affiliates, Sponsors & Referrals: https://lmg.gg/sponsors 1173 | ►Check out our podcast gear: https://kit.co/linustechtips/lmg-podcast-gear 1174 | ►Private Internet Access VPN: https://lmg.gg/pialinus2 1175 | ►Our Official Charging Partner Anker: https://lmg.gg/AnkerLTT 1176 | ►MK Keyboards: https://lmg.gg/LyLtl 1177 | ►Nerd or Die Stream Overlays: https://lmg.gg/avLlO 1178 | ►Official Game Store: https://www.nexus.gg/ltt 1179 | ►Amazon Prime: https://lmg.gg/8KV1v 1180 | ►Audible Free Trial: https://lmg.gg/8242J 1181 | ►Our Gear on Amazon: https://geni.us/OhmF 1182 | 1183 | FOLLOW US ELSEWHERE 1184 | --------------------------------------------------- 1185 | Twitter: https://twitter.com/linustech 1186 | Facebook: http://www.facebook.com/LinusTech 1187 | Instagram: https://www.instagram.com/linustech 1188 | Twitch: https://www.twitch.tv/linustech 1189 | 1190 | FOLLOW OUR OTHER CHANNELS 1191 | --------------------------------------------------- 1192 | Mac Address: https://lmg.gg/macaddress 1193 | Techquickie: https://lmg.gg/techquickieyt 1194 | TechLinked: https://lmg.gg/techlinkedyt 1195 | ShortCircuit: https://lmg.gg/shortcircuityt 1196 | 1197 | LMG Clips: https://lmg.gg/lmgclipsyt 1198 | Channel Super Fun: https://lmg.gg/channelsuperfunyt 1199 | Carpool Critics: https://lmg.gg/carpoolcriticsyt 1200 | 1201 | MUSIC CREDIT 1202 | --------------------------------------------------- 1203 | Title: Laszlo - Supernova 1204 | Video Link: https://www.youtube.com/watch?v=PKfxmFU3lWY 1205 | iTunes Download Link: https://itunes.apple.com/us/album/supernova/id936805712 1206 | Artist Link: https://soundcloud.com/laszlomusic 1207 | 1208 | Outro Screen Music Credit: Approaching Nirvana - Sugar High http://www.youtube.com/approachingnirvana 1209 | 1210 | Monitor And Keyboard by vadimmihalkevich / CC BY 4.0 https://geni.us/PgGWp 1211 | Mechanical RGB Keyboard by BigBrotherECE / CC BY 4.0 https://geni.us/mj6pHk4 1212 | Mouse Gamer free Model By Oscar Creativo / CC BY 4.0 https://geni.us/Ps3XfE 1213 | 1214 | CHAPTERS 1215 | --------------------------------------------------- 1216 | 0:00 Intro 1217 | 0:38 What ARE these? 1218 | 1:55 Anbernic RG351M 1219 | 6:22 Retroid Pocket 2 1220 | 10:53 ODROID-Go Super 1221 | 14:47 Some history 1222 | 16:18 Piracy 1223 | 17:13 Conclusion 1224 | 1225 | 1226 | 1227 | 1228 | 1229 | 1230 | 1231 | yt:video:ShtiJ8Y2alE 1232 | ShtiJ8Y2alE 1233 | UCXuqSBlHAE6Xw-yeJA0Tunw 1234 | The PRACTICAL Tech Transformation - Intel $5,000 Extreme Tech Upgrade 1235 | 1236 | 1237 | Linus Tech Tips 1238 | https://www.youtube.com/channel/UCXuqSBlHAE6Xw-yeJA0Tunw 1239 | 1240 | 2021-07-17T17:02:16+00:00 1241 | 2021-07-18T17:09:24+00:00 1242 | 1243 | The PRACTICAL Tech Transformation - Intel $5,000 Extreme Tech Upgrade 1244 | 1245 | 1246 | Thanks to Intel for sponsoring this series! Check out the Intel Core i9-10850K (PAID LINK): https://geni.us/4w11 1247 | 1248 | Buy Intel Core i9-10850K CPU 1249 | On Amazon (PAID LINK): https://geni.us/2Vp22w 1250 | On Best Buy (PAID LINK): https://geni.us/53Fd0b 1251 | On Newegg (PAID LINK): https://geni.us/HAOo 1252 | 1253 | Buy ASUS ROG Strix Z490-E 1254 | On Amazon (PAID LINK): https://geni.us/BA46A 1255 | On Best Buy (PAID LINK): https://geni.us/SGyOBjK 1256 | On Newegg (PAID LINK): https://geni.us/8u1A 1257 | 1258 | Buy Crucial Ballistix 16GB (8GBx2) DDR4 RAM 1259 | On Amazon (PAID LINK): https://geni.us/zmnR 1260 | 1261 | Buy Toshiba X300 4TB HDD 1262 | On Amazon (PAID LINK): https://geni.us/nmuFVm 1263 | On Newegg (PAID LINK): https://geni.us/FedBkw4 1264 | 1265 | Buy Seasonic Syncro Q7 Case 1266 | On Newegg (PAID LINK): https://geni.us/Z56ORJ 1267 | 1268 | Buy EVGA RTX 3080 Ti XC3 Ultra Gaming GPU 1269 | On Amazon (PAID LINK): https://geni.us/Kgo2eGa 1270 | On Best Buy (PAID LINK): https://geni.us/AB2X8as 1271 | On Newegg (PAID LINK): https://geni.us/SuPpM 1272 | 1273 | Buy HP ENVY 14 (2021) 1274 | On HP (PAID LINK): https://geni.us/vAsvKv9 1275 | On Amazon (PAID LINK): https://geni.us/ki3OM9 1276 | On B&H (PAID LINK): https://geni.us/eBZJp 1277 | 1278 | Buy Microsoft Surface Headphones 2 1279 | On Amazon (PAID LINK): https://geni.us/CCfc 1280 | On Best Buy (PAID LINK): https://geni.us/n0KzT 1281 | On Newegg (PAID LINK): https://geni.us/K2BCFn 1282 | 1283 | Buy Dell S2721D Monitor 1284 | On Amazon (PAID LINK): https://geni.us/hotR 1285 | 1286 | Buy Logitech G305 LIGHTSPEED Wireless Gaming Mouse 1287 | On Amazon (PAID LINK): https://geni.us/p5UJT 1288 | On Best Buy (PAID LINK): https://geni.us/ON7Ln 1289 | On Newegg (PAID LINK): https://geni.us/dkCQx8f 1290 | 1291 | Buy Logitech K400 Plus Wireless TV Keyboard 1292 | On Amazon (PAID LINK): https://geni.us/6QUBcNY 1293 | On Newegg (PAID LINK): https://geni.us/futfB8P 1294 | On B&H (PAID LINK): https://geni.us/l7Ogrxw 1295 | 1296 | Buy Philips Hue Smart Lightstrip Plus 2m/6ft Base Kit 1297 | On Amazon (PAID LINK): https://geni.us/hpyyWT 1298 | On Best Buy (PAID LINK): https://geni.us/uDpeF 1299 | On B&H (PAID LINK): https://geni.us/B0MOaC 1300 | 1301 | Buy Logitech K845 Mechanical Keyboard 1302 | On Amazon (PAID LINK): https://geni.us/DfiiA 1303 | On Newegg (PAID LINK): https://geni.us/3AOePr 1304 | On B&H (PAID LINK): https://geni.us/GJoo 1305 | 1306 | Buy RODE PSA 1 Microphone Boom Arm 1307 | On Amazon (PAID LINK): https://geni.us/QoOiI 1308 | On Best Buy (PAID LINK): https://geni.us/tFNzQm 1309 | On Newegg (PAID LINK): https://geni.us/eSi1G 1310 | Purchases made through some store links may provide some compensation to Linus Media Group. 1311 | 1312 | Discuss on the forum: https://linustechtips.com/topic/1357288-a-big-tech-transformation-intel-5000-extreme-tech-upgrade/ 1313 | 1314 | ►GET MERCH: http://www.LTTStore.com/ 1315 | ►SUPPORT US ON FLOATPLANE: https://www.floatplane.com/ 1316 | ►LTX EXPO: https://www.ltxexpo.com/ 1317 | 1318 | AFFILIATES & REFERRALS 1319 | --------------------------------------------------- 1320 | ►Affiliates, Sponsors & Referrals: https://lmg.gg/sponsors 1321 | ►Check out our podcast gear: https://kit.co/linustechtips/lmg-podcast-gear 1322 | ►Private Internet Access VPN: https://lmg.gg/pialinus2 1323 | ►Our Official Charging Partner Anker: https://lmg.gg/AnkerLTT 1324 | ►MK Keyboards: https://lmg.gg/LyLtl 1325 | ►Nerd or Die Stream Overlays: https://lmg.gg/avLlO 1326 | ►Official Game Store: https://www.nexus.gg/ltt 1327 | ►Amazon Prime: https://lmg.gg/8KV1v 1328 | ►Audible Free Trial: https://lmg.gg/8242J 1329 | ►Our Gear on Amazon: https://geni.us/OhmF 1330 | 1331 | FOLLOW US ELSEWHERE 1332 | --------------------------------------------------- 1333 | Twitter: https://twitter.com/linustech 1334 | Facebook: http://www.facebook.com/LinusTech 1335 | Instagram: https://www.instagram.com/linustech 1336 | Twitch: https://www.twitch.tv/linustech 1337 | 1338 | FOLLOW OUR OTHER CHANNELS 1339 | --------------------------------------------------- 1340 | Mac Address: https://lmg.gg/macaddress 1341 | Techquickie: https://lmg.gg/techquickieyt 1342 | TechLinked: https://lmg.gg/techlinkedyt 1343 | ShortCircuit: https://lmg.gg/shortcircuityt 1344 | 1345 | LMG Clips: https://lmg.gg/lmgclipsyt 1346 | Channel Super Fun: https://lmg.gg/channelsuperfunyt 1347 | Carpool Critics: https://lmg.gg/carpoolcriticsyt 1348 | 1349 | MUSIC CREDIT 1350 | --------------------------------------------------- 1351 | Title: Laszlo - Supernova 1352 | Video Link: https://www.youtube.com/watch?v=PKfxmFU3lWY 1353 | iTunes Download Link: https://itunes.apple.com/us/album/supernova/id936805712 1354 | Artist Link: https://soundcloud.com/laszlomusic 1355 | 1356 | Outro Screen Music Credit: Approaching Nirvana - Sugar High http://www.youtube.com/approachingnirvana 1357 | 1358 | Monitor And Keyboard by vadimmihalkevich / CC BY 4.0 https://geni.us/PgGWp 1359 | Mechanical RGB Keyboard by BigBrotherECE / CC BY 4.0 https://geni.us/mj6pHk4 1360 | Mouse Gamer free Model By Oscar Creativo / CC BY 4.0 https://geni.us/Ps3XfE 1361 | 1362 | CHAPTERS 1363 | --------------------------------------------------- 1364 | 0:00 Intro 1365 | 1366 | 1367 | 1368 | 1369 | 1370 | 1371 | 1372 | yt:video:60NGxX7m1Mw 1373 | 60NGxX7m1Mw 1374 | UCXuqSBlHAE6Xw-yeJA0Tunw 1375 | The Most Exciting Gaming PC in YEARS - WAN Show July 16, 2021 1376 | 1377 | 1378 | Linus Tech Tips 1379 | https://www.youtube.com/channel/UCXuqSBlHAE6Xw-yeJA0Tunw 1380 | 1381 | 2021-07-17T03:06:50+00:00 1382 | 2021-07-19T20:11:37+00:00 1383 | 1384 | The Most Exciting Gaming PC in YEARS - WAN Show July 16, 2021 1385 | 1386 | 1387 | Visit https://www.squarespace.com/WAN and use offer code WAN for 10% off 1388 | 1389 | Try Pulseway for free and start remotely monitoring and managing your server or PC at https://geni.us/pulseway 1390 | 1391 | Save 10% at Ridge Wallet with offer code WAN at https://www.ridge.com/WAN 1392 | 1393 | Podcast Download: https://anchor.fm/thewanshowpodcast/episodes/The-Most-Exciting-Gaming-PC-in-YEARS---WAN-Show-July-16--2021-e14n0jd 1394 | 1395 | Check out our other Podcasts: 1396 | Carpool Critics Movie Podcast: https://www.youtube.com/channel/UCt-oJR5teQIjOAxCmIQvcgA 1397 | 1398 | Timestamps (Courtesy of Chico Veinte Minutos): 1399 | 0:00 Presentation 1400 | 1:16 Intro 1401 | 1:47 Steam Deck 1402 | 38:29 GitHub Co-Pilot 1403 | 47:18 Sponsors 1404 | 49:57 TSMC exploring new ways to cool silicon chips 1405 | 53:30 Intel is in talks to buy Global Foundries 1406 | 56:02 AMD Fidelity FX is now Open Source 1407 | 58:20 Microsoft announces Windows 360 1408 | 1:01:00 Alder Lake Leak 1409 | 1:03:50 Reprint of the old LTT underwear 1410 | 1:04:40 "Gaming" on Netflix 1411 | 1:05:11 Superchats 1412 | 1:13:25 Steam Deck RDNA 2 Graphics Mention 1413 | 1414 | 1415 | 1416 | 1417 | 1418 | 1419 | 1420 | yt:video:PjDgKXe8gxs 1421 | PjDgKXe8gxs 1422 | UCXuqSBlHAE6Xw-yeJA0Tunw 1423 | Gaming at Max Settings is Really Dumb 1424 | 1425 | 1426 | Linus Tech Tips 1427 | https://www.youtube.com/channel/UCXuqSBlHAE6Xw-yeJA0Tunw 1428 | 1429 | 2021-07-15T17:00:07+00:00 1430 | 2021-07-17T12:15:54+00:00 1431 | 1432 | Gaming at Max Settings is Really Dumb 1433 | 1434 | 1435 | Check out the Drop x Sennheiser HD 6XX Headphones at https://dro.ps/6xx-ltt-07 1436 | 1437 | Use code LINUS and get 25% off GlassWire at https://lmg.gg/glasswire 1438 | 1439 | Why do max settings even exist if we can barely run them? Should you buy a 3080 or 3090 if you have an older monitor, or will your older card keep you afloat for the time being? 1440 | 1441 | Buy NZXT N7 Z590 1442 | On Amazon (PAID LINK): https://geni.us/HBs1qH 1443 | 1444 | Buy G.SKILL TridentZ RGB 16GB (2 x 8GB) RAM 1445 | On Amazon (PAID LINK): https://geni.us/OSOK 1446 | On Newegg (PAID LINK): https://geni.us/jAFgv 1447 | 1448 | Buy Crucial P5 500GB NVMe SSD 1449 | On Amazon (PAID LINK): https://geni.us/OI2Fq5x 1450 | On Best Buy (PAID LINK): https://geni.us/oaNB 1451 | On Newegg (PAID LINK): https://geni.us/65Wgiv 1452 | 1453 | Buy Intel Core i7-11700K CPU 1454 | On Amazon (PAID LINK): https://geni.us/KGFUHY 1455 | On Best Buy (PAID LINK): https://geni.us/0gkr 1456 | On Newegg (PAID LINK): https://geni.us/U4vfVqC 1457 | 1458 | Buy ASUS TUF RTX 3090 GPU 1459 | On Amazon (PAID LINK): https://geni.us/cBo90R 1460 | On Best Buy (PAID LINK): https://geni.us/BJt7o2 1461 | On Newegg (PAID LINK): https://geni.us/wXsY 1462 | 1463 | Purchases made through some store links may provide some compensation to Linus Media Group. 1464 | 1465 | Discuss on the forum: https://linustechtips.com/topic/1356695-gaming-at-max-settings-is-really-dumb/ 1466 | 1467 | 1468 | ►GET MERCH: http://www.LTTStore.com/ 1469 | ►SUPPORT US ON FLOATPLANE: https://www.floatplane.com/ 1470 | ►LTX EXPO: https://www.ltxexpo.com/ 1471 | 1472 | AFFILIATES & REFERRALS 1473 | --------------------------------------------------- 1474 | ►Affiliates, Sponsors & Referrals: https://lmg.gg/sponsors 1475 | ►Check out our podcast gear: https://kit.co/linustechtips/lmg-podcast-gear 1476 | ►Private Internet Access VPN: https://lmg.gg/pialinus2 1477 | ►Our Official Charging Partner Anker: https://lmg.gg/AnkerLTT 1478 | ►MK Keyboards: https://lmg.gg/LyLtl 1479 | ►Nerd or Die Stream Overlays: https://lmg.gg/avLlO 1480 | ►Official Game Store: https://www.nexus.gg/ltt 1481 | ►Amazon Prime: https://lmg.gg/8KV1v 1482 | ►Audible Free Trial: https://lmg.gg/8242J 1483 | ►Our Gear on Amazon: https://geni.us/OhmF 1484 | 1485 | FOLLOW US ELSEWHERE 1486 | --------------------------------------------------- 1487 | Twitter: https://twitter.com/linustech 1488 | Facebook: http://www.facebook.com/LinusTech 1489 | Instagram: https://www.instagram.com/linustech 1490 | Twitch: https://www.twitch.tv/linustech 1491 | 1492 | FOLLOW OUR OTHER CHANNELS 1493 | --------------------------------------------------- 1494 | Mac Address: https://lmg.gg/macaddress 1495 | Techquickie: https://lmg.gg/techquickieyt 1496 | TechLinked: https://lmg.gg/techlinkedyt 1497 | ShortCircuit: https://lmg.gg/shortcircuityt 1498 | 1499 | LMG Clips: https://lmg.gg/lmgclipsyt 1500 | Channel Super Fun: https://lmg.gg/channelsuperfunyt 1501 | Carpool Critics: https://lmg.gg/carpoolcriticsyt 1502 | 1503 | MUSIC CREDIT 1504 | --------------------------------------------------- 1505 | Title: Laszlo - Supernova 1506 | Video Link: https://www.youtube.com/watch?v=PKfxmFU3lWY 1507 | iTunes Download Link: https://itunes.apple.com/us/album/supernova/id936805712 1508 | Artist Link: https://soundcloud.com/laszlomusic 1509 | 1510 | Outro Screen Music Credit: Approaching Nirvana - Sugar High http://www.youtube.com/approachingnirvana 1511 | 1512 | Monitor And Keyboard by vadimmihalkevich / CC BY 4.0 https://geni.us/PgGWp 1513 | Mechanical RGB Keyboard by BigBrotherECE / CC BY 4.0 https://geni.us/mj6pHk4 1514 | Mouse Gamer free Model By Oscar Creativo / CC BY 4.0 https://geni.us/Ps3XfE 1515 | 1516 | CHAPTERS 1517 | --------------------------------------------------- 1518 | 0:00 Intro 1519 | 1:30 Our Test 1520 | 2:12 Results Discussion 1521 | 3:37 Performance Targets 1522 | 5:05 Monkey 1523 | 6:02 Noticeable Settings 1524 | 6:45 Final Thoughts 1525 | 8:33 Outro 1526 | 1527 | 1528 | 1529 | 1530 | 1531 | 1532 | -------------------------------------------------------------------------------- /spec/fixtures/files/youtube_playlist.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | yt:playlist:PLMEZyDHJojxMRL0ifs67xcfzTOiPrGMdF 5 | PLMEZyDHJojxMRL0ifs67xcfzTOiPrGMdF 6 | UC5GOr7CavTbxAf18CKjukdg 7 | Ramones playlist - BEST songs 8 | 9 | Radio Golcak 10 | https://www.youtube.com/channel/UC5GOr7CavTbxAf18CKjukdg 11 | 12 | 2015-04-22T16:09:39+00:00 13 | 14 | yt:video:K56soYl0U1w 15 | K56soYl0U1w 16 | UCbLByZawHMZx_TFppHXeNYw 17 | The Ramones - Blitzkrieg Bop (With Lyrics) 18 | 19 | 20 | EA0825 21 | https://www.youtube.com/channel/UCbLByZawHMZx_TFppHXeNYw 22 | 23 | 2009-05-11T02:01:07+00:00 24 | 2021-06-29T15:19:02+00:00 25 | 26 | The Ramones - Blitzkrieg Bop (With Lyrics) 27 | 28 | 29 | description 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | yt:video:F3J0iwwsq-w 38 | F3J0iwwsq-w 39 | UCFXgCHrEv679zbK9v5yCRcA 40 | Ramones - Pet Sematary 41 | 42 | 43 | BoPTePegar 44 | https://www.youtube.com/channel/UCFXgCHrEv679zbK9v5yCRcA 45 | 46 | 2009-05-10T23:23:32+00:00 47 | 2021-06-04T07:52:01+00:00 48 | 49 | Ramones - Pet Sematary 50 | 51 | 52 | description 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | yt:video:OfIfzVf8t6E 61 | OfIfzVf8t6E 62 | UCGwgulq7fGfXK7nJvxVYTZA 63 | Ramones - Poison Heart (Official Video) 64 | 65 | 66 | RamonesVEVO 67 | https://www.youtube.com/channel/UCGwgulq7fGfXK7nJvxVYTZA 68 | 69 | 2009-11-23T00:44:18+00:00 70 | 2021-06-29T06:40:59+00:00 71 | 72 | Ramones - Poison Heart (Official Video) 73 | 74 | 75 | description 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | yt:video:PqZmJ7RGAP4 84 | PqZmJ7RGAP4 85 | UChwj00Akf8AW6rd-vMz9QZg 86 | The Ramones-Baby I Love You 87 | 88 | 89 | MatthewNabokovfan88 90 | https://www.youtube.com/channel/UChwj00Akf8AW6rd-vMz9QZg 91 | 92 | 2008-11-24T00:52:10+00:00 93 | 2021-07-04T23:52:04+00:00 94 | 95 | The Ramones-Baby I Love You 96 | 97 | 98 | description 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | yt:video:NMCJYfutZ8Y 107 | NMCJYfutZ8Y 108 | UC5GOr7CavTbxAf18CKjukdg 109 | Radio Golcak - The Best Playlists on YouTube 110 | 111 | 112 | Radio Golcak 113 | https://www.youtube.com/channel/UC5GOr7CavTbxAf18CKjukdg 114 | 115 | 2016-08-03T16:15:58+00:00 116 | 2021-05-21T09:11:32+00:00 117 | 118 | Radio Golcak - The Best Playlists on YouTube 119 | 120 | 121 | description 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | yt:video:vmNerf4kea4 130 | vmNerf4kea4 131 | UCQMv35EH3Ee1m7OsDkrKr1w 132 | Ramones - I Want You Around (Video) 133 | 134 | 135 | GlamMetalSucks 136 | https://www.youtube.com/channel/UCQMv35EH3Ee1m7OsDkrKr1w 137 | 138 | 2009-05-31T17:48:01+00:00 139 | 2021-06-04T07:44:35+00:00 140 | 141 | Ramones - I Want You Around (Video) 142 | 143 | 144 | description 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | yt:video:eRwek-qyyeM 153 | eRwek-qyyeM 154 | UC9Hb9kfme2I-hQN97N541Qg 155 | The Ramones - I Just Want To Have Something To Do [HD] 156 | 157 | 158 | Ƶombie 159 | https://www.youtube.com/channel/UC9Hb9kfme2I-hQN97N541Qg 160 | 161 | 2012-08-05T03:57:24+00:00 162 | 2021-06-04T07:56:42+00:00 163 | 164 | The Ramones - I Just Want To Have Something To Do [HD] 165 | 166 | 167 | description 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | yt:video:fGWR3uI3Qa0 176 | fGWR3uI3Qa0 177 | UCia3sM3GMVzQhau9GcO7i6w 178 | RAMONES - Needles & Pins 179 | 180 | 181 | Ramones ♪ 182 | https://www.youtube.com/channel/UCia3sM3GMVzQhau9GcO7i6w 183 | 184 | 2009-09-21T04:31:05+00:00 185 | 2021-06-04T07:49:39+00:00 186 | 187 | RAMONES - Needles & Pins 188 | 189 | 190 | description 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | yt:video:i5P8lrgBtcU 199 | i5P8lrgBtcU 200 | UCy4LN-5yaFGwrNxwRPbq3wQ 201 | Ramones - Spider-Man 202 | 203 | 204 | MACVSOG84 205 | https://www.youtube.com/channel/UCy4LN-5yaFGwrNxwRPbq3wQ 206 | 207 | 2007-06-20T10:11:25+00:00 208 | 2021-06-29T23:34:29+00:00 209 | 210 | Ramones - Spider-Man 211 | 212 | 213 | description 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | yt:video:9BCTgMbLn_Q 222 | 9BCTgMbLn_Q 223 | UCZDjRj_pjO-G5AT90q0aCaw 224 | The Ramones - I Wanna Live 225 | 226 | 227 | Flowers Of Romance 228 | https://www.youtube.com/channel/UCZDjRj_pjO-G5AT90q0aCaw 229 | 230 | 2010-05-11T22:57:18+00:00 231 | 2021-06-29T13:07:33+00:00 232 | 233 | The Ramones - I Wanna Live 234 | 235 | 236 | description 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | yt:video:6siGKxcKol0 245 | 6siGKxcKol0 246 | UCia3sM3GMVzQhau9GcO7i6w 247 | RAMONES - Rockaway Beach 248 | 249 | 250 | Ramones ♪ 251 | https://www.youtube.com/channel/UCia3sM3GMVzQhau9GcO7i6w 252 | 253 | 2009-09-17T09:54:19+00:00 254 | 2021-06-04T07:50:01+00:00 255 | 256 | RAMONES - Rockaway Beach 257 | 258 | 259 | description 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | yt:video:CVQfVtzFd4U 268 | CVQfVtzFd4U 269 | UCia3sM3GMVzQhau9GcO7i6w 270 | RAMONES - Surfin' Bird 271 | 272 | 273 | Ramones ♪ 274 | https://www.youtube.com/channel/UCia3sM3GMVzQhau9GcO7i6w 275 | 276 | 2009-09-18T10:59:41+00:00 277 | 2021-06-04T07:42:10+00:00 278 | 279 | RAMONES - Surfin' Bird 280 | 281 | 282 | description 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | yt:video:wIWpfS_MFHw 291 | wIWpfS_MFHw 292 | UCGwgulq7fGfXK7nJvxVYTZA 293 | Ramones - Substitute 294 | 295 | 296 | RamonesVEVO 297 | https://www.youtube.com/channel/UCGwgulq7fGfXK7nJvxVYTZA 298 | 299 | 2009-12-20T08:28:02+00:00 300 | 2021-06-29T18:42:30+00:00 301 | 302 | Ramones - Substitute 303 | 304 | 305 | Music video by Ramones performing Substitute. YouTube view counts pre-VEVO: 143,285 (C) 1994 Radioactive Records J.V. 306 | 307 | 308 | 309 | 310 | 311 | 312 | -------------------------------------------------------------------------------- /spec/jobs/fix_topic_embed_authors_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rails_helper" 4 | 5 | RSpec.describe Jobs::DiscourseRssPolling::FixTopicEmbedAuthors do 6 | let(:job) { Jobs::DiscourseRssPolling::FixTopicEmbedAuthors.new } 7 | 8 | describe "#execute" do 9 | before { Jobs.run_later! } 10 | 11 | it "makes sure the topic and first post have the same author" do 12 | Sidekiq::Testing.fake! do 13 | topic_embed = create_mismatched_topic_embed 14 | post = topic_embed.post 15 | expected_user = post.user 16 | 17 | expect(post.user).to_not eq(post.topic.user) 18 | 19 | job.execute({}) 20 | 21 | post.reload 22 | expect(post.user).to eq(expected_user) 23 | expect(post.user).to eq(post.topic.user) 24 | end 25 | end 26 | 27 | def create_mismatched_topic_embed 28 | topic_embed = Fabricate(:topic_embed, embed_url: "http://example.com/post/248") 29 | new_user = Fabricate(:user) 30 | 31 | topic_embed.post.revise( 32 | Discourse.system_user, 33 | { user_id: new_user.id }, 34 | skip_validations: true, 35 | bypass_rate_limiter: true, 36 | ) 37 | 38 | topic_embed 39 | end 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /spec/jobs/poll_all_feeds_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rails_helper" 4 | 5 | RSpec.describe Jobs::DiscourseRssPolling::PollAllFeeds do 6 | SiteSetting.rss_polling_enabled = true 7 | let(:job) { Jobs::DiscourseRssPolling::PollAllFeeds.new } 8 | 9 | describe "#execute" do 10 | before do 11 | DiscourseRssPolling::RssFeed.create!(url: "https://www.example.com/feed", author: "system") 12 | DiscourseRssPolling::RssFeed.create!( 13 | url: "https://blog.discourse.org/feed/", 14 | author: "discourse", 15 | ) 16 | 17 | Jobs.run_later! 18 | Discourse.redis.del("rss-polling-feeds-polled") 19 | end 20 | 21 | it "queues correct PollFeed jobs" do 22 | Sidekiq::Testing.fake! do 23 | expect { job.execute({}) }.to change { Jobs::DiscourseRssPolling::PollFeed.jobs.size }.by(2) 24 | 25 | enqueued_jobs_args = 26 | Jobs::DiscourseRssPolling::PollFeed.jobs.last(2).map { |job| job["args"][0] } 27 | 28 | expect(enqueued_jobs_args[0]["feed_url"]).to eq("https://www.example.com/feed") 29 | expect(enqueued_jobs_args[0]["author_username"]).to eq("system") 30 | 31 | expect(enqueued_jobs_args[1]["feed_url"]).to eq("https://blog.discourse.org/feed/") 32 | expect(enqueued_jobs_args[1]["author_username"]).to eq("discourse") 33 | end 34 | end 35 | 36 | it "is rate limited" do 37 | Sidekiq::Testing.fake! do 38 | expect { job.execute({}) }.to change { Jobs::DiscourseRssPolling::PollFeed.jobs.size }.by(2) 39 | expect { job.execute({}) }.to_not change { Jobs::DiscourseRssPolling::PollFeed.jobs.size } 40 | end 41 | end 42 | 43 | context "when the plugin is disabled" do 44 | before { SiteSetting.rss_polling_enabled = false } 45 | 46 | it "does not queue PollFeed jobs" do 47 | Sidekiq::Testing.fake! do 48 | expect { job.execute({}) }.not_to change { Jobs::DiscourseRssPolling::PollFeed.jobs.size } 49 | end 50 | end 51 | end 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /spec/jobs/poll_feed_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rails_helper" 4 | 5 | RSpec.describe Jobs::DiscourseRssPolling::PollFeed do 6 | SiteSetting.rss_polling_enabled = true 7 | let(:feed_url) { "https://blog.discourse.org/feed/" } 8 | let(:author) { Fabricate(:user, trust_level: 1) } 9 | let(:raw_feed) { file_from_fixtures("feed.rss", "feed") } 10 | let(:job) { Jobs::DiscourseRssPolling::PollFeed.new } 11 | 12 | describe "#execute" do 13 | before do 14 | Discourse.redis.del("rss-polling-feed-polled:#{Digest::SHA1.hexdigest(feed_url)}") 15 | stub_request(:head, feed_url).to_return(status: 200, body: "") 16 | stub_request(:get, feed_url).to_return(status: 200, body: raw_feed) 17 | end 18 | 19 | it "creates a topic with the right title, content and author" do 20 | expect { job.execute(feed_url: feed_url, author_username: author.username) }.to change { 21 | author.topics.count 22 | } 23 | 24 | topic = author.topics.last 25 | 26 | expect(topic.title).to eq("Poll Feed Spec Fixture") 27 | expect(topic.first_post.raw).to include("

This is the body & content.

") 28 | expect(topic.topic_embed.embed_url).to eq( 29 | "https://blog.discourse.org/2017/09/poll-feed-spec-fixture", 30 | ) 31 | end 32 | 33 | context "with use_pubdate set to false" do 34 | before do 35 | SiteSetting.rss_polling_use_pubdate = false 36 | job.execute(feed_url: feed_url, author_username: author.username) 37 | end 38 | 39 | it "has a publication date of now" do 40 | topic = author.topics.last 41 | expect(topic.created_at.utc).to be_within(1.second).of Time.now 42 | expect(topic.first_post.created_at.utc).to be_within(1.second).of Time.now 43 | end 44 | end 45 | 46 | context "with use_pubdate set to true" do 47 | before do 48 | SiteSetting.rss_polling_use_pubdate = true 49 | job.execute(feed_url: feed_url, author_username: author.username) 50 | end 51 | 52 | it "has a publication date of the feed" do 53 | topic = author.topics.last 54 | expect(topic.created_at).to eq_time(DateTime.parse("2017-09-14 15:22:33.000000000 +0000")) 55 | expect(topic.first_post.created_at).to eq_time( 56 | DateTime.parse("2017-09-14 15:22:33.000000000 +0000"), 57 | ) 58 | end 59 | end 60 | 61 | context "with a previous poll on a topic with tags" do 62 | let(:tag1) { Fabricate(:tag, name: "test-from-rss") } 63 | let(:tag2) { Fabricate(:tag, name: "test-update-from-rss") } 64 | 65 | before do 66 | SiteSetting.tagging_enabled = true 67 | job.execute( 68 | feed_url: feed_url, 69 | author_username: author.username, 70 | discourse_tags: [tag1.name], 71 | ) 72 | Discourse.redis.del("rss-polling-feed-polled:#{Digest::SHA1.hexdigest(feed_url)}") 73 | end 74 | 75 | context "with rss polling set to true" do 76 | before { SiteSetting.rss_polling_update_tags = true } 77 | it "updates tags by default" do 78 | topic = author.topics.last 79 | job.execute( 80 | feed_url: feed_url, 81 | author_username: author.username, 82 | discourse_tags: [tag2.name], 83 | ) 84 | topic = author.topics.last.reload 85 | expect(topic.tags).to match_array([tag2]) 86 | end 87 | end 88 | 89 | context "with rss polling set to false" do 90 | before { SiteSetting.rss_polling_update_tags = false } 91 | 92 | it "does not update tags" do 93 | job.execute( 94 | feed_url: feed_url, 95 | author_username: author.username, 96 | discourse_tags: [tag2.name], 97 | ) 98 | topic = author.topics.last 99 | expect(topic.tags).to match_array([tag1]) 100 | end 101 | end 102 | end 103 | 104 | it "is rate limited by rss_polling_frequency" do 105 | 2.times { job.execute(feed_url: feed_url, author_username: author.username) } 106 | 107 | expect(WebMock).to have_requested(:get, feed_url).once 108 | end 109 | 110 | it "is not raising error if http request failed" do 111 | stub_request(:get, feed_url).to_raise(Excon::Error::HTTPStatus) 112 | job.execute(feed_url: feed_url, author_username: author.username) 113 | end 114 | 115 | it "skips the topic if the category doesn't exist on our side" do 116 | invalid_discourse_category_id = 99 117 | 118 | expect { 119 | job.execute( 120 | feed_url: feed_url, 121 | author_username: author.username, 122 | discourse_category_id: invalid_discourse_category_id, 123 | ) 124 | }.not_to change { author.topics.count } 125 | 126 | expect(author.topics.last).to be_nil 127 | end 128 | 129 | it "does not raise error for valid xml but non-rss content" do 130 | stub_request(:get, feed_url).to_return(status: 200, body: "tesing") 131 | 132 | expect { 133 | job.execute(feed_url: feed_url, author_username: author.username) 134 | }.not_to raise_error 135 | end 136 | 137 | it "does not raise error for valid xml but non-rss title" do 138 | stub_request(:get, feed_url).to_return( 139 | status: 200, 140 | body: rss_polling_file_fixture("mastodon.rss").read, 141 | ) 142 | 143 | expect { 144 | job.execute(feed_url: feed_url, author_username: author.username) 145 | }.not_to raise_error 146 | end 147 | end 148 | end 149 | -------------------------------------------------------------------------------- /spec/models/feed_item_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rails_helper" 4 | require "rss" 5 | 6 | RSpec.describe DiscourseRssPolling::FeedItem do 7 | RSpec.shared_examples "correctly parses the feed" do |**expected| 8 | let(:feed_item) { DiscourseRssPolling::FeedItem.new(raw_feed_item) } 9 | 10 | it { expect(feed_item.content).to eq(expected[:content]) } 11 | it { expect(feed_item.url).to eq(expected[:url]) } 12 | it { expect(feed_item.title).to eq(expected[:title]) } 13 | end 14 | 15 | context "with empty item" do 16 | let(:raw_feed_item) { {} } 17 | include_examples("correctly parses the feed", content: nil, url: nil, title: nil) 18 | end 19 | 20 | context "with RSS item" do 21 | let(:feed) { RSS::Parser.parse(file_from_fixtures("feed.rss", "feed")) } 22 | let(:raw_feed_item) { feed.items.first } 23 | 24 | include_examples( 25 | "correctly parses the feed", 26 | content: "

This is the body & content.

", 27 | url: "https://blog.discourse.org/2017/09/poll-feed-spec-fixture/", 28 | title: "Poll Feed Spec Fixture", 29 | ) 30 | end 31 | 32 | context "with escaped title" do 33 | let(:raw_feed) { rss_polling_file_fixture("escaped_html.atom").read } 34 | let(:feed) { RSS::Parser.parse(raw_feed) } 35 | let(:raw_feed_item) { feed.entries.first } 36 | 37 | include_examples( 38 | "correctly parses the feed", 39 | content: "Here are some random descriptions...", 40 | url: "https://blog.discourse.org/2017/09/poll-feed-spec-fixture/", 41 | title: "Wellington: “Progress is hard!” Other cities: “Hold my beer”", 42 | ) 43 | end 44 | 45 | context "with ATOM item with content element" do 46 | let(:feed) { RSS::Parser.parse(file_from_fixtures("feed.atom", "feed")) } 47 | let(:raw_feed_item) { feed.entries.first } 48 | 49 | include_examples( 50 | "correctly parses the feed", 51 | content: "

This is the body & content.

", 52 | url: "https://blog.discourse.org/2017/09/poll-feed-spec-fixture/", 53 | title: "Poll Feed Spec Fixture", 54 | ) 55 | end 56 | 57 | context "with ATOM item with summary element" do 58 | let(:raw_feed) { rss_polling_file_fixture("no_content_only_summary.atom").read } 59 | let(:feed) { RSS::Parser.parse(raw_feed) } 60 | let(:raw_feed_item) { feed.entries.first } 61 | 62 | include_examples( 63 | "correctly parses the feed", 64 | content: "Here are some random descriptions...", 65 | url: "https://blog.discourse.org/2017/09/poll-feed-spec-fixture/", 66 | title: "Poll Feed Spec Fixture", 67 | ) 68 | end 69 | 70 | context "with ATOM items with categories elements" do 71 | let(:raw_feed) { rss_polling_file_fixture("multiple_categories.atom").read } 72 | let(:feed) { RSS::Parser.parse(raw_feed, false) } 73 | let(:raw_feed_item) { feed.entries.first } 74 | 75 | include_examples( 76 | "correctly parses the feed", 77 | content: "Here are some random descriptions...", 78 | url: "https://blog.discourse.org/2017/09/poll-feed-spec-fixture/", 79 | title: "Poll Feed Spec Fixture", 80 | categories: ["spec", "xrav3nz diary"], 81 | ) 82 | end 83 | 84 | context "with Youtube playlist" do 85 | let(:raw_feed) { rss_polling_file_fixture("youtube_playlist.xml").read } 86 | let(:feed) { RSS::Parser.parse(raw_feed, false) } 87 | let(:raw_feed_item) { feed.entries.first } 88 | 89 | include_examples( 90 | "correctly parses the feed", 91 | content: "https://www.youtube.com/watch?v=K56soYl0U1w", 92 | url: "https://www.youtube.com/watch?v=K56soYl0U1w", 93 | title: "The Ramones - Blitzkrieg Bop (With Lyrics)", 94 | ) 95 | end 96 | 97 | context "with youtube channel" do 98 | let(:raw_feed) { rss_polling_file_fixture("youtube_channel.xml").read } 99 | let(:feed) { RSS::Parser.parse(raw_feed, false) } 100 | let(:raw_feed_item) { feed.entries.first } 101 | 102 | include_examples( 103 | "correctly parses the feed", 104 | content: "https://www.youtube.com/watch?v=peYYl2vrIt4", 105 | url: "https://www.youtube.com/watch?v=peYYl2vrIt4", 106 | title: "An Uncontroversial Opinion – AMD RX 6600 XT Announcement", 107 | ) 108 | end 109 | end 110 | -------------------------------------------------------------------------------- /spec/models/feed_setting_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rails_helper" 4 | 5 | RSpec.describe DiscourseRssPolling::FeedSetting do 6 | SiteSetting.rss_polling_enabled = true 7 | let(:feed_url) { "https://blog.discourse.org/feed/" } 8 | let(:author) { Fabricate(:user, refresh_auto_groups: true) } 9 | let(:category) { Fabricate(:category) } 10 | let(:tag) { Fabricate(:tag) } 11 | let(:feed_category_filter) { "spec" } 12 | let(:feed_setting) do 13 | DiscourseRssPolling::FeedSetting.new( 14 | feed_url: feed_url, 15 | author_username: author.username, 16 | discourse_category_id: category.id, 17 | discourse_tags: [tag.name], 18 | feed_category_filter: feed_category_filter, 19 | ) 20 | end 21 | let(:wrong_feed_setting) do 22 | DiscourseRssPolling::FeedSetting.new( 23 | feed_url: feed_url, 24 | author_username: author.username, 25 | discourse_category_id: category.id, 26 | discourse_tags: [tag.name], 27 | feed_category_filter: "non existing category", 28 | ) 29 | end 30 | let(:missing_username_feed_setting) do 31 | DiscourseRssPolling::FeedSetting.new( 32 | feed_url: feed_url, 33 | author_username: nil, 34 | discourse_category_id: category.id, 35 | discourse_tags: [tag.name], 36 | feed_category_filter: feed_category_filter, 37 | ) 38 | end 39 | let(:poll_feed_job) { Jobs::DiscourseRssPolling::PollFeed } 40 | 41 | describe "#poll" do 42 | context "with inline: false" do 43 | before { Jobs.run_later! } 44 | 45 | it "enqueues a Jobs::DiscourseRssPolling::PollFeed job with the correct arguments" do 46 | Sidekiq::Testing.fake! do 47 | expect { feed_setting.poll }.to change(poll_feed_job.jobs, :size).by(1) 48 | 49 | enqueued_job = poll_feed_job.jobs.last 50 | 51 | expect(enqueued_job["args"][0]["feed_url"]).to eq(feed_url) 52 | expect(enqueued_job["args"][0]["author_username"]).to eq(author.username) 53 | expect(enqueued_job["args"][0]["discourse_category_id"]).to eq(category.id) 54 | expect(enqueued_job["args"][0]["discourse_tags"]).to eq([tag.name]) 55 | expect(enqueued_job["args"][0]["feed_category_filter"]).to eq(feed_category_filter) 56 | end 57 | end 58 | end 59 | 60 | context "with inline: true" do 61 | before { SiteSetting.tagging_enabled = true } 62 | 63 | it "polls and the feed and creates the new topics" do 64 | Discourse.redis.del("rss-polling-feed-polled:#{Digest::SHA1.hexdigest(feed_url)}") 65 | stub_request(:head, feed_url).to_return(status: 200, body: "") 66 | stub_request(:get, feed_url).to_return( 67 | status: 200, 68 | body: file_from_fixtures("feed.rss", "feed"), 69 | ) 70 | 71 | expect { feed_setting.poll(inline: true) }.to change { author.topics.count } 72 | 73 | topic = author.topics.last 74 | 75 | expect(topic.title).to eq("Poll Feed Spec Fixture") 76 | expect(topic.first_post.raw).to include("

This is the body & content.

") 77 | expect(topic.topic_embed.embed_url).to eq( 78 | "https://blog.discourse.org/2017/09/poll-feed-spec-fixture", 79 | ) 80 | expect(topic.category).to eq(category) 81 | expect(topic.tags.first.name).to eq(tag.name) 82 | end 83 | 84 | it "polls and the feed and does not create the new topics because of the category filter" do 85 | Discourse.redis.del("rss-polling-feed-polled:#{Digest::SHA1.hexdigest(feed_url)}") 86 | stub_request(:head, feed_url).to_return(status: 200, body: "") 87 | stub_request(:get, feed_url).to_return( 88 | status: 200, 89 | body: file_from_fixtures("feed.rss", "feed"), 90 | ) 91 | 92 | expect { wrong_feed_setting.poll(inline: true) }.not_to change { author.topics.count } 93 | end 94 | 95 | it "does not create the new topics because of the missing username" do 96 | Discourse.redis.del("rss-polling-feed-polled:#{Digest::SHA1.hexdigest(feed_url)}") 97 | stub_request(:head, feed_url).to_return(status: 200, body: "") 98 | stub_request(:get, feed_url).to_return( 99 | status: 200, 100 | body: file_from_fixtures("feed.rss", "feed"), 101 | ) 102 | 103 | expect { missing_username_feed_setting.poll(inline: true) }.not_to change { Topic.count } 104 | end 105 | end 106 | end 107 | end 108 | -------------------------------------------------------------------------------- /spec/plugin_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module RssPollingSpecHelper 4 | FILE_FIXTURE_PATH = File.expand_path("fixtures/files", File.dirname(__FILE__)) 5 | 6 | def rss_polling_file_fixture(fixture_name) 7 | Pathname.new(File.join(FILE_FIXTURE_PATH, fixture_name)) 8 | end 9 | end 10 | 11 | RSpec.configure { |config| config.include RssPollingSpecHelper } 12 | -------------------------------------------------------------------------------- /spec/requests/feed_settings_controller_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rails_helper" 4 | 5 | describe DiscourseRssPolling::FeedSettingsController do 6 | let!(:admin) { Fabricate(:admin) } 7 | 8 | before do 9 | sign_in(admin) 10 | 11 | SiteSetting.rss_polling_enabled = true 12 | end 13 | 14 | describe "#show" do 15 | before do 16 | DiscourseRssPolling::RssFeed.create!( 17 | url: "https://blog.discourse.org/feed", 18 | author: "system", 19 | category_id: 4, 20 | tags: nil, 21 | category_filter: "updates", 22 | ) 23 | end 24 | 25 | it "returns the serialized feed settings" do 26 | expected_json = 27 | ActiveModel::ArraySerializer.new( 28 | DiscourseRssPolling::FeedSettingFinder.all, 29 | root: :feed_settings, 30 | ).to_json 31 | 32 | get "/admin/plugins/rss_polling/feed_settings.json" 33 | 34 | expect(response.status).to eq(200) 35 | expect(response.body).to eq(expected_json) 36 | end 37 | end 38 | 39 | describe "#update" do 40 | it "updates rss feeds" do 41 | put "/admin/plugins/rss_polling/feed_settings.json", 42 | params: { 43 | feed_setting: { 44 | feed_url: "https://www.newsite.com/feed", 45 | author_username: "system", 46 | feed_category_filter: "updates", 47 | }, 48 | } 49 | 50 | expect(response.status).to eq(200) 51 | feeds = DiscourseRssPolling::FeedSettingFinder.all 52 | expect(feeds.count).to eq(1) 53 | end 54 | 55 | it "allows duplicate rss feed urls" do 56 | put "/admin/plugins/rss_polling/feed_settings.json", 57 | params: { 58 | feed_setting: { 59 | feed_url: "https://blog.discourse.org/feed", 60 | author_username: "system", 61 | discourse_category_id: 2, 62 | feed_category_filter: "updates", 63 | }, 64 | } 65 | 66 | expect(response.status).to eq(200) 67 | 68 | put "/admin/plugins/rss_polling/feed_settings.json", 69 | params: { 70 | feed_setting: { 71 | feed_url: "https://blog.discourse.org/feed", 72 | author_username: "system", 73 | discourse_category_id: 4, 74 | feed_category_filter: "updates", 75 | }, 76 | } 77 | 78 | expect(response.status).to eq(200) 79 | feeds = DiscourseRssPolling::FeedSettingFinder.all 80 | expect(feeds.count).to eq(2) 81 | end 82 | end 83 | end 84 | -------------------------------------------------------------------------------- /spec/services/feed_setting_finder_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rails_helper" 4 | 5 | RSpec.describe DiscourseRssPolling::FeedSettingFinder do 6 | before do 7 | DiscourseRssPolling::RssFeed.create!(url: "https://blog.discourse.org/feed/", author: "system") 8 | DiscourseRssPolling::RssFeed.create!(url: "https://www.withwww.com/feed", author: "system") 9 | DiscourseRssPolling::RssFeed.create!(url: "https://withoutwww.com/feed", author: "system") 10 | end 11 | 12 | describe ".by_embed_url" do 13 | it "finds the feed setting with the same host" do 14 | setting = 15 | DiscourseRssPolling::FeedSettingFinder.by_embed_url("https://blog.discourse.org/2018/03/") 16 | expect(setting.feed_url).to eq("https://blog.discourse.org/feed/") 17 | end 18 | 19 | it "neglects www in the url" do 20 | setting = DiscourseRssPolling::FeedSettingFinder.by_embed_url("https://withwww.com/a-post/") 21 | expect(setting.feed_url).to eq("https://www.withwww.com/feed") 22 | 23 | setting = 24 | DiscourseRssPolling::FeedSettingFinder.by_embed_url("https://www.withoutwww.com/a-post/") 25 | expect(setting.feed_url).to eq("https://withoutwww.com/feed") 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /spec/system/core_features_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | RSpec.describe "Core features", type: :system do 4 | before { enable_current_plugin } 5 | 6 | it_behaves_like "having working core features" 7 | end 8 | -------------------------------------------------------------------------------- /stylelint.config.mjs: -------------------------------------------------------------------------------- 1 | export default { 2 | extends: ["@discourse/lint-configs/stylelint"], 3 | }; 4 | -------------------------------------------------------------------------------- /translator.yml: -------------------------------------------------------------------------------- 1 | # Configuration file for discourse-translator-bot 2 | 3 | files: 4 | - source_path: config/locales/client.en.yml 5 | destination_path: client.yml 6 | - source_path: config/locales/server.en.yml 7 | destination_path: server.yml 8 | --------------------------------------------------------------------------------