├── .npmrc ├── .prettierrc.cjs ├── .template-lintrc.cjs ├── .streerc ├── stylelint.config.mjs ├── .rubocop.yml ├── eslint.config.mjs ├── Gemfile ├── .gitignore ├── admin └── assets │ └── javascripts │ └── admin │ ├── controllers │ ├── admin-plugins-house-ads.js │ ├── admin-plugins-house-ads-index.js │ └── admin-plugins-house-ads-show.js │ ├── components │ ├── house-ads-category-selector.gjs │ ├── modal │ │ └── preview.gjs │ ├── house-ads-chooser.js │ ├── house-ads-list-setting.gjs │ └── house-ads-setting.gjs │ ├── adplugin-route-map.js │ ├── routes │ ├── admin-plugins-house-ads-index.js │ ├── admin-plugins-house-ads.js │ └── admin-plugins-house-ads-show.js │ └── templates │ ├── plugins-house-ads.gjs │ ├── plugins-house-ads-index.gjs │ └── plugins-house-ads-show.gjs ├── spec ├── system │ ├── core_features_spec.rb │ └── admin_house_ad_spec.rb ├── requests │ ├── house_ad_settings_controller_spec.rb │ ├── house_ad_controller_spec.rb │ └── site_controller_spec.rb ├── serializer │ └── current_user_serializer_spec.rb └── models │ └── house_ad_setting_spec.rb ├── config └── locales │ ├── server.bg.yml │ ├── server.da.yml │ ├── server.hr.yml │ ├── server.hu.yml │ ├── server.id.yml │ ├── server.lt.yml │ ├── server.lv.yml │ ├── server.sk.yml │ ├── server.sl.yml │ ├── server.sq.yml │ ├── server.sr.yml │ ├── server.te.yml │ ├── server.th.yml │ ├── server.ug.yml │ ├── client.en_GB.yml │ ├── server.bs_BA.yml │ ├── server.en_GB.yml │ ├── server.vi.yml │ ├── client.id.yml │ ├── client.sr.yml │ ├── client.bg.yml │ ├── client.hr.yml │ ├── client.sq.yml │ ├── client.te.yml │ ├── client.ug.yml │ ├── client.be.yml │ ├── client.lv.yml │ ├── client.sl.yml │ ├── client.gl.yml │ ├── client.el.yml │ ├── client.hu.yml │ ├── client.sw.yml │ ├── client.da.yml │ ├── client.sk.yml │ ├── client.nb_NO.yml │ ├── client.et.yml │ ├── client.lt.yml │ ├── client.vi.yml │ ├── client.pt.yml │ ├── server.ro.yml │ ├── client.cs.yml │ ├── client.hy.yml │ ├── client.fa_IR.yml │ ├── client.ro.yml │ ├── client.zh_TW.yml │ ├── server.et.yml │ ├── client.ko.yml │ ├── client.th.yml │ ├── client.bs_BA.yml │ ├── client.zh_CN.yml │ ├── client.ur.yml │ ├── client.uk.yml │ ├── client.ca.yml │ ├── client.ja.yml │ ├── client.sv.yml │ ├── client.pl_PL.yml │ ├── client.en.yml │ ├── client.he.yml │ ├── client.ar.yml │ ├── client.tr_TR.yml │ ├── client.fi.yml │ ├── client.it.yml │ ├── client.ru.yml │ ├── client.pt_BR.yml │ ├── client.fr.yml │ ├── client.es.yml │ ├── client.nl.yml │ ├── client.de.yml │ ├── server.zh_TW.yml │ ├── server.gl.yml │ ├── server.nb_NO.yml │ ├── server.cs.yml │ ├── server.fa_IR.yml │ └── server.pt.yml ├── translator.yml ├── .github └── workflows │ └── discourse-plugin.yml ├── assets ├── javascripts │ └── discourse │ │ ├── components │ │ ├── post-bottom-ad.gjs │ │ ├── carbonads-ad.gjs │ │ ├── ad-component.js │ │ ├── adbutler-ad.gjs │ │ └── house-ad.gjs │ │ ├── helpers │ │ └── slot-position.js │ │ ├── connectors │ │ ├── discovery-list-container-top │ │ │ └── discourse-adplugin.gjs │ │ ├── topic-above-suggested │ │ │ └── discourse-adplugin.gjs │ │ ├── topic-above-post-stream │ │ │ └── discourse-adplugin.gjs │ │ └── after-topic-list-item │ │ │ └── discourse-adplugin.gjs │ │ └── initializers │ │ └── initialize-ad-plugin.gjs └── stylesheets │ └── adplugin.scss ├── app ├── controllers │ ├── house_ad_settings_controller.rb │ ├── adstxt_controller.rb │ └── house_ads_controller.rb └── models │ ├── house_ad_setting.rb │ └── house_ad.rb ├── db └── migrate │ ├── 20190603112536_rename_site_setting_ads_txt.rb │ ├── 20200703082449_remove_codefund_site_settings.rb │ ├── 20250721192556_enable_adplugin_if_already_installed.rb │ ├── 20240208195102_migrate_dfp_to_exclude_groups.rb │ ├── 20240208195101_migrate_amazon_to_exclude_groups.rb │ ├── 20240208195103_migrate_carbon_to_exclude_groups.rb │ ├── 20240208195100_migrate_adsense_to_exclude_groups.rb │ ├── 20240118195156_migrate_tl_to_group_settings_dfp_through_tl.rb │ ├── 20240118195157_migrate_tl_to_group_settings_amazon_through_tl.rb │ ├── 20240208195104_migrate_adbutler_to_exclude_groups.rb │ ├── 20240118195155_migrate_tl_to_group_settings_adsense_through_tl.rb │ ├── 20240118195159_migrate_tl_to_group_settings_adbutler_through_tl.rb │ └── 20240118195158_migrate_tl_to_group_settings_carbonads_through_tl.rb ├── package.json ├── .discourse-compatibility ├── lib └── adplugin │ └── guardian_extensions.rb ├── LICENSE.txt ├── test └── javascripts │ └── acceptance │ ├── mixed-ads-test.js │ ├── dfp-test.js │ └── adsense-test.js ├── Gemfile.lock └── plugin.rb /.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict = true 2 | auto-install-peers = false 3 | -------------------------------------------------------------------------------- /.prettierrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = require("@discourse/lint-configs/prettier"); 2 | -------------------------------------------------------------------------------- /.template-lintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = require("@discourse/lint-configs/template-lint"); 2 | -------------------------------------------------------------------------------- /.streerc: -------------------------------------------------------------------------------- 1 | --print-width=100 2 | --plugins=plugin/trailing_comma,plugin/disable_auto_ternary 3 | -------------------------------------------------------------------------------- /stylelint.config.mjs: -------------------------------------------------------------------------------- 1 | export default { 2 | extends: ["@discourse/lint-configs/stylelint"], 3 | }; 4 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | inherit_gem: 2 | rubocop-discourse: stree-compat.yml 3 | 4 | RSpec/NamedSubject: 5 | Enabled: false -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import DiscourseRecommended from "@discourse/lint-configs/eslint"; 2 | 3 | export default [...DiscourseRecommended]; 4 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .bundle/ 2 | log/*.log 3 | pkg/ 4 | auto_generated 5 | .DS_Store 6 | *.swp 7 | node_modules 8 | yarn-error.log 9 | .rubocop-https---raw-githubusercontent-com-discourse-* 10 | -------------------------------------------------------------------------------- /admin/assets/javascripts/admin/controllers/admin-plugins-house-ads.js: -------------------------------------------------------------------------------- 1 | import Controller from "@ember/controller"; 2 | 3 | export default class AdminPluginsHouseAdsController extends Controller { 4 | loadingAds = true; 5 | } 6 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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.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/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.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.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 | -------------------------------------------------------------------------------- /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.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.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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /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/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.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 | -------------------------------------------------------------------------------- /admin/assets/javascripts/admin/components/house-ads-category-selector.gjs: -------------------------------------------------------------------------------- 1 | import CategorySelector from "select-kit/components/category-selector"; 2 | 3 | export default class HouseAdsCategorySelector extends CategorySelector { 4 | get value() { 5 | return this.selectedCategories.map((c) => c.id); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /assets/javascripts/discourse/components/post-bottom-ad.gjs: -------------------------------------------------------------------------------- 1 | import AdSlot from "./ad-slot"; 2 | 3 | const PostBottomAd = ; 10 | 11 | export default PostBottomAd; 12 | -------------------------------------------------------------------------------- /admin/assets/javascripts/admin/adplugin-route-map.js: -------------------------------------------------------------------------------- 1 | export default { 2 | resource: "admin.adminPlugins", 3 | path: "/plugins", 4 | map() { 5 | this.route("houseAds", { path: "/pluginad/house_creatives" }, function () { 6 | this.route("index", { path: "/" }); 7 | this.route("show", { path: "/:ad_id" }); 8 | }); 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /app/controllers/house_ad_settings_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ::AdPlugin 4 | class HouseAdSettingsController < ::ApplicationController 5 | requires_plugin AdPlugin.plugin_name 6 | 7 | def update 8 | HouseAdSetting.update(params[:id], params[:value]) 9 | render json: success_json 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /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 | site_settings: 9 | amazon_mobile_topic_list_top_src_code: "Nhập mã src để hiển thị quảng cáo di động ở vị trí hàng đầu trong danh sách chủ đề" 10 | -------------------------------------------------------------------------------- /db/migrate/20190603112536_rename_site_setting_ads_txt.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class RenameSiteSettingAdsTxt < ActiveRecord::Migration[5.2] 4 | def up 5 | execute "UPDATE site_settings SET name = 'ads_txt' WHERE name = 'adsense_ads_txt'" 6 | end 7 | 8 | def down 9 | execute "UPDATE site_settings SET name = 'adsense_ads_txt' WHERE name = 'ads_txt'" 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/controllers/adstxt_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # 3 | class AdstxtController < ::ApplicationController 4 | requires_plugin AdPlugin.plugin_name 5 | 6 | skip_before_action :preload_json, :check_xhr, :redirect_to_login_if_required 7 | 8 | def index 9 | raise Discourse::NotFound if SiteSetting.ads_txt.blank? 10 | 11 | render plain: SiteSetting.ads_txt 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.discourse-compatibility: -------------------------------------------------------------------------------- 1 | < 3.5.0.beta8-dev: e51aad3bfd41cf2cb9557e025e833122a9f6c892 2 | < 3.5.0.beta5-dev: bd9af0b9a577bfd2c01cc8b81a782a4e8b81b9c5 3 | < 3.5.0.beta1-dev: 6ceba62e985223c269782c4bc9a1bdc4a5adba28 4 | < 3.4.0.beta2-dev: 7685ebf396c93e8accc5a76a81fcec4384a73fa3 5 | < 3.4.0.beta1-dev: da38a4c053b68d7076db4441cfe86b473979945d 6 | < 3.3.0.beta1-dev: 062efc8a547c19474eaeefae464837d63a5e5fb3 7 | 3.1.999: 30c49eb50d6d16fcf82bace3da0e1972b7b220c0 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 | admin_js: 9 | admin: 10 | adplugin: 11 | house_ads: 12 | new: "Baru" 13 | settings: "Pengaturan" 14 | save: "Simpan" 15 | delete: "Hapus" 16 | -------------------------------------------------------------------------------- /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 | admin_js: 9 | admin: 10 | adplugin: 11 | house_ads: 12 | new: "Novo" 13 | settings: "Podešavanje" 14 | save: "Sačuvaj" 15 | delete: "Obriši" 16 | -------------------------------------------------------------------------------- /admin/assets/javascripts/admin/routes/admin-plugins-house-ads-index.js: -------------------------------------------------------------------------------- 1 | import { action } from "@ember/object"; 2 | import { service } from "@ember/service"; 3 | import DiscourseRoute from "discourse/routes/discourse"; 4 | 5 | export default class AdminPluginsHouseAdsIndex extends DiscourseRoute { 6 | @service router; 7 | 8 | @action 9 | moreSettings() { 10 | this.router.transitionTo("adminSiteSettingsCategory", "ad_plugin"); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /admin/assets/javascripts/admin/controllers/admin-plugins-house-ads-index.js: -------------------------------------------------------------------------------- 1 | import Controller, { inject as controller } from "@ember/controller"; 2 | import { alias } from "@ember/object/computed"; 3 | 4 | export default class AdminPluginsHouseAdsIndexController extends Controller { 5 | @controller("adminPlugins.houseAds") adminPluginsHouseAds; 6 | 7 | @alias("adminPluginsHouseAds.model") houseAds; 8 | @alias("adminPluginsHouseAds.houseAdsSettings") adSettings; 9 | } 10 | -------------------------------------------------------------------------------- /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 | admin_js: 9 | admin: 10 | adplugin: 11 | house_ads: 12 | new: "Нов" 13 | settings: "Настройки" 14 | save: "Запази" 15 | delete: "Изтрий" 16 | preview: "Преглед" 17 | -------------------------------------------------------------------------------- /assets/javascripts/discourse/helpers/slot-position.js: -------------------------------------------------------------------------------- 1 | export function isNthPost(every, currentPostNumber) { 2 | if (every && every > 0) { 3 | return currentPostNumber % every === 0; 4 | } else { 5 | return false; 6 | } 7 | } 8 | 9 | export function isNthTopicListItem(every, currentIndexPosition) { 10 | if (every && every > 0 && currentIndexPosition > 0) { 11 | return (currentIndexPosition + 1) % every === 0; 12 | } else { 13 | return false; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /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 | admin_js: 9 | admin: 10 | adplugin: 11 | house_ads: 12 | new: "Novo" 13 | settings: "Postavke" 14 | save: "Spremi" 15 | delete: "Pobriši" 16 | preview: "Pregled" 17 | -------------------------------------------------------------------------------- /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 | admin_js: 9 | admin: 10 | adplugin: 11 | house_ads: 12 | new: "I Ri" 13 | settings: "Rregullimet" 14 | save: "Ruaj" 15 | delete: "Fshij" 16 | preview: "Parashikimi" 17 | -------------------------------------------------------------------------------- /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 | admin_js: 9 | admin: 10 | adplugin: 11 | house_ads: 12 | new: "కొత్త" 13 | settings: "అమరికలు" 14 | save: "భద్రపరచు" 15 | delete: "తొలగించు" 16 | preview: "ప్రివ్యూ" 17 | -------------------------------------------------------------------------------- /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 | admin_js: 9 | admin: 10 | adplugin: 11 | house_ads: 12 | new: "يېڭى" 13 | settings: "تەڭشەكلەر" 14 | save: "ساقلا" 15 | delete: "ئۆچۈر" 16 | preview: "ئالدىن كۆزەت" 17 | -------------------------------------------------------------------------------- /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 | admin_js: 9 | admin: 10 | adplugin: 11 | house_ads: 12 | new: "Новая" 13 | settings: "Налады" 14 | save: "Захаваць" 15 | delete: "Выдаліць" 16 | preview: "Папярэдні прагляд" 17 | -------------------------------------------------------------------------------- /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 | admin_js: 9 | admin: 10 | adplugin: 11 | house_ads: 12 | new: "Jauns" 13 | settings: "Iestatījumi" 14 | save: "Saglabāt" 15 | delete: "Dzēst" 16 | preview: "Priekšskatījums" 17 | -------------------------------------------------------------------------------- /assets/javascripts/discourse/connectors/discovery-list-container-top/discourse-adplugin.gjs: -------------------------------------------------------------------------------- 1 | import Component from "@ember/component"; 2 | import { classNames, tagName } from "@ember-decorators/component"; 3 | import AdSlot from "../../components/ad-slot"; 4 | 5 | @tagName("span") 6 | @classNames("discovery-list-container-top-outlet", "discourse-adplugin") 7 | export default class DiscourseAdplugin extends Component { 8 | 11 | } 12 | -------------------------------------------------------------------------------- /admin/assets/javascripts/admin/components/modal/preview.gjs: -------------------------------------------------------------------------------- 1 | import { htmlSafe } from "@ember/template"; 2 | import DModal from "discourse/components/d-modal"; 3 | import { i18n } from "discourse-i18n"; 4 | 5 | const Preview = ; 17 | 18 | export default Preview; 19 | -------------------------------------------------------------------------------- /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 | js: 9 | adplugin: 10 | advertisement_label: "OGLAS" 11 | admin_js: 12 | admin: 13 | adplugin: 14 | house_ads: 15 | new: "Novi" 16 | settings: "Nastavitve" 17 | save: "Shrani" 18 | delete: "Izbriši" 19 | preview: "Predogled" 20 | -------------------------------------------------------------------------------- /assets/javascripts/discourse/connectors/topic-above-suggested/discourse-adplugin.gjs: -------------------------------------------------------------------------------- 1 | import Component from "@ember/component"; 2 | import { classNames, tagName } from "@ember-decorators/component"; 3 | import AdSlot from "../../components/ad-slot"; 4 | 5 | @tagName("div") 6 | @classNames("topic-above-suggested-outlet", "discourse-adplugin") 7 | export default class DiscourseAdplugin extends Component { 8 | 14 | } 15 | -------------------------------------------------------------------------------- /assets/javascripts/discourse/connectors/topic-above-post-stream/discourse-adplugin.gjs: -------------------------------------------------------------------------------- 1 | import Component from "@ember/component"; 2 | import { classNames, tagName } from "@ember-decorators/component"; 3 | import AdSlot from "../../components/ad-slot"; 4 | 5 | @tagName("div") 6 | @classNames("topic-above-post-stream-outlet", "discourse-adplugin") 7 | export default class DiscourseAdplugin extends Component { 8 | 14 | } 15 | -------------------------------------------------------------------------------- /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 | admin_js: 9 | admin: 10 | site_settings: 11 | categories: 12 | amazon_plugin: "Amazon" 13 | adplugin: 14 | house_ads: 15 | new: "Novo" 16 | settings: "Axustes" 17 | save: "Gardar" 18 | delete: "Eliminar" 19 | preview: "Visualizar" 20 | -------------------------------------------------------------------------------- /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 | admin_js: 9 | admin: 10 | site_settings: 11 | categories: 12 | amazon_plugin: "Amazon" 13 | adplugin: 14 | house_ads: 15 | new: "Νέο" 16 | settings: "Ρυθμίσεις" 17 | save: "Αποθήκευση" 18 | delete: "Σβήσιμο" 19 | preview: "Προεπισκόπηση" 20 | -------------------------------------------------------------------------------- /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 | js: 9 | adplugin: 10 | advertisement_label: "HIRDETÉS" 11 | admin_js: 12 | admin: 13 | site_settings: 14 | categories: 15 | amazon_plugin: "Amazon" 16 | adplugin: 17 | house_ads: 18 | new: "Új" 19 | settings: "Beállítások" 20 | save: "Mentés" 21 | delete: "Töröl" 22 | preview: "Előnézet" 23 | -------------------------------------------------------------------------------- /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 | js: 9 | adplugin: 10 | advertisement_label: "TANGAZO" 11 | admin_js: 12 | admin: 13 | site_settings: 14 | categories: 15 | amazon_plugin: "Amazon" 16 | adplugin: 17 | house_ads: 18 | new: "Mpya" 19 | settings: "Mpangilio" 20 | save: "hifadhi" 21 | delete: "Futa" 22 | preview: "Kihakiki" 23 | -------------------------------------------------------------------------------- /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 | js: 9 | adplugin: 10 | advertisement_label: "REKLAME" 11 | admin_js: 12 | admin: 13 | site_settings: 14 | categories: 15 | amazon_plugin: "Amazon" 16 | adplugin: 17 | house_ads: 18 | new: "Ny" 19 | settings: "Indstillinger" 20 | save: "Gem" 21 | delete: "Slet" 22 | preview: "Forhåndsvisning" 23 | -------------------------------------------------------------------------------- /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 | js: 9 | adplugin: 10 | advertisement_label: "РЕКЛАМА" 11 | admin_js: 12 | admin: 13 | site_settings: 14 | categories: 15 | amazon_plugin: "Amazon" 16 | adplugin: 17 | house_ads: 18 | new: "Nový" 19 | settings: "Nastavenia" 20 | save: "Uložiť" 21 | delete: "Odstrániť" 22 | preview: "Ukážka" 23 | -------------------------------------------------------------------------------- /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 | js: 9 | adplugin: 10 | advertisement_label: "REKLAME" 11 | admin_js: 12 | admin: 13 | site_settings: 14 | categories: 15 | amazon_plugin: "Amazon" 16 | adplugin: 17 | house_ads: 18 | new: "Ny" 19 | settings: "Innstillinger" 20 | save: "Lagre" 21 | delete: "Slett" 22 | preview: "Forhåndsvis" 23 | -------------------------------------------------------------------------------- /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 | js: 9 | adplugin: 10 | advertisement_label: "REKLAAM" 11 | admin_js: 12 | admin: 13 | site_settings: 14 | categories: 15 | adsense_plugin: "AdSense" 16 | amazon_plugin: "Amazon" 17 | adplugin: 18 | house_ads: 19 | new: "Uus" 20 | settings: "Seaded" 21 | save: "Salvesta" 22 | delete: "Kustuta" 23 | preview: "Eelvaade" 24 | -------------------------------------------------------------------------------- /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 | js: 9 | adplugin: 10 | advertisement_label: "REKLAMA" 11 | admin_js: 12 | admin: 13 | site_settings: 14 | categories: 15 | dfp_plugin: "DFP/Ad Redaktorius" 16 | amazon_plugin: "Amazon" 17 | adplugin: 18 | house_ads: 19 | new: "Naujas" 20 | settings: "Nustatymai" 21 | save: "Saugoti" 22 | delete: "Pašalinti" 23 | preview: "Peržiūrėti" 24 | -------------------------------------------------------------------------------- /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 | js: 9 | adplugin: 10 | advertisement_label: "QUẢNG CÁO" 11 | admin_js: 12 | admin: 13 | site_settings: 14 | categories: 15 | ad_plugin: "Ad Plugin" 16 | dfp_plugin: "Trình quản lý quảng cáo DFP/Ad" 17 | adsense_plugin: "AdSense" 18 | adplugin: 19 | house_ads: 20 | new: "Mới" 21 | settings: "Xác lập" 22 | save: "Lưu" 23 | delete: "Xóa" 24 | preview: "Xem trước" 25 | -------------------------------------------------------------------------------- /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 | js: 9 | adplugin: 10 | advertisement_label: "Publicidade" 11 | admin_js: 12 | admin: 13 | site_settings: 14 | categories: 15 | dfp_plugin: "Gestor de DFP/Ad" 16 | adsense_plugin: "AdSense" 17 | amazon_plugin: "Amazon" 18 | adplugin: 19 | house_ads: 20 | new: "Novo" 21 | settings: "Configurações" 22 | save: "Guardar" 23 | delete: "Eliminar" 24 | preview: "Pré-visualização" 25 | -------------------------------------------------------------------------------- /admin/assets/javascripts/admin/routes/admin-plugins-house-ads.js: -------------------------------------------------------------------------------- 1 | import EmberObject from "@ember/object"; 2 | import { ajax } from "discourse/lib/ajax"; 3 | import DiscourseRoute from "discourse/routes/discourse"; 4 | 5 | export default class AdminPluginsHouseAds extends DiscourseRoute { 6 | settings = null; 7 | 8 | model() { 9 | return ajax("/admin/plugins/pluginad/house_creatives.json").then((data) => { 10 | this.set("settings", EmberObject.create(data.settings)); 11 | return data.house_ads.map((ad) => EmberObject.create(ad)); 12 | }); 13 | } 14 | 15 | setupController(controller, model) { 16 | controller.setProperties({ 17 | model, 18 | houseAdsSettings: this.get("settings"), 19 | loadingAds: false, 20 | }); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /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 | dfp_exclude_groups: "Anunțurile nu vor fi afișate membrilor acestor grupuri" 10 | adsense_exclude_groups: "Anunțurile nu vor fi afișate membrilor acestor grupuri" 11 | amazon_exclude_groups: "Anunțurile nu vor fi afișate membrilor acestor grupuri" 12 | carbonads_exclude_groups: "Anunțurile nu vor fi afișate membrilor acestor grupuri" 13 | carbonads_topic_list_top_enabled: "Afișează o reclamă deasupra listei de discuții" 14 | adbutler_exclude_groups: "Anunțurile nu vor fi afișate membrilor acestor grupuri" 15 | -------------------------------------------------------------------------------- /admin/assets/javascripts/admin/routes/admin-plugins-house-ads-show.js: -------------------------------------------------------------------------------- 1 | import { TrackedObject } from "@ember-compat/tracked-built-ins"; 2 | import DiscourseRoute from "discourse/routes/discourse"; 3 | import { i18n } from "discourse-i18n"; 4 | 5 | export default class AdminPluginsHouseAdsShow extends DiscourseRoute { 6 | model(params) { 7 | if (params.ad_id === "new") { 8 | return new TrackedObject({ 9 | name: i18n("admin.adplugin.house_ads.new_name"), 10 | html: "", 11 | visible_to_logged_in_users: true, 12 | visible_to_anons: true, 13 | }); 14 | } else { 15 | return new TrackedObject( 16 | this.modelFor("adminPlugins.houseAds").findBy( 17 | "id", 18 | parseInt(params.ad_id, 10) 19 | ) 20 | ); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /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 | js: 9 | adplugin: 10 | advertisement_label: "REKLAMA" 11 | admin_js: 12 | admin: 13 | site_settings: 14 | categories: 15 | ad_plugin: "Plugin pro reklamu" 16 | dfp_plugin: "Správce DFP/AD" 17 | adsense_plugin: "AdSense" 18 | amazon_plugin: "Amazon" 19 | carbonads_plugin: "Uhlíkové reklamy" 20 | adplugin: 21 | house_ads: 22 | new: "Noví" 23 | settings: "Nastavení" 24 | save: "Uložit" 25 | delete: "Smazat" 26 | preview: "Náhled" 27 | -------------------------------------------------------------------------------- /db/migrate/20200703082449_remove_codefund_site_settings.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class RemoveCodefundSiteSettings < ActiveRecord::Migration[5.2] 4 | def up 5 | execute <<~SQL 6 | DELETE FROM site_settings 7 | WHERE name IN ( 8 | 'codefund_property_id', 9 | 'codefund_advertiser_label', 10 | 'codefund_advertiser_short_label', 11 | 'codefund_through_trust_level', 12 | 'codefund_nth_post', 13 | 'codefund_display_advertiser_labels', 14 | 'codefund_below_post_enabled', 15 | 'codefund_above_post_stream_enabled', 16 | 'codefund_above_suggested_enabled', 17 | 'codefund_top_of_topic_list_enabled' 18 | ) 19 | SQL 20 | end 21 | 22 | def down 23 | raise ActiveRecord::IrreversibleMigration 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /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 | js: 9 | adplugin: 10 | advertisement_label: "ՀԱՅՏԱՐԱՐՈՒԹՅՈՒՆ" 11 | admin_js: 12 | admin: 13 | site_settings: 14 | categories: 15 | ad_plugin: "Ad Plugin" 16 | dfp_plugin: "DFP/Ad Manager" 17 | adsense_plugin: "AdSense" 18 | amazon_plugin: "Amazon" 19 | carbonads_plugin: "Ածխածնի գովազդ" 20 | adbutler_plugin: "AdButler" 21 | adplugin: 22 | house_ads: 23 | new: "Նոր" 24 | settings: "Կարգավորումներ" 25 | save: "Պահպանել" 26 | delete: "Ջնջել" 27 | preview: "Նախադիտում" 28 | -------------------------------------------------------------------------------- /lib/adplugin/guardian_extensions.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ::AdPlugin 4 | module GuardianExtensions 5 | def show_dfp_ads? 6 | !self.user.in_any_groups?(SiteSetting.dfp_exclude_groups_map) 7 | end 8 | 9 | def show_adsense_ads? 10 | !self.user.in_any_groups?(SiteSetting.adsense_exclude_groups_map) 11 | end 12 | 13 | def show_carbon_ads? 14 | !self.user.in_any_groups?(SiteSetting.carbonads_exclude_groups_map) 15 | end 16 | 17 | def show_amazon_ads? 18 | !self.user.in_any_groups?(SiteSetting.amazon_exclude_groups_map) 19 | end 20 | 21 | def show_adbutler_ads? 22 | !self.user.in_any_groups?(SiteSetting.adbutler_exclude_groups_map) 23 | end 24 | 25 | def show_to_groups? 26 | !self.user.in_any_groups?(SiteSetting.no_ads_for_groups_map) 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /db/migrate/20250721192556_enable_adplugin_if_already_installed.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class EnableAdpluginIfAlreadyInstalled < ActiveRecord::Migration[7.2] 4 | def up 5 | installed_at = DB.query_single(<<~SQL)&.first 6 | SELECT created_at FROM schema_migration_details WHERE version='20190603112536' 7 | SQL 8 | 9 | if installed_at && installed_at < 1.hour.ago 10 | # The plugin was installed before we changed it to be disabled-by-default 11 | # Therefore, if there is no existing database value, enable the plugin 12 | execute <<~SQL 13 | INSERT INTO site_settings(name, data_type, value, created_at, updated_at) 14 | VALUES('discourse_adplugin_enabled', 5, 't', NOW(), NOW()) 15 | ON CONFLICT (name) DO NOTHING 16 | SQL 17 | end 18 | end 19 | 20 | def down 21 | raise ActiveRecord::IrreversibleMigration 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /assets/javascripts/discourse/connectors/after-topic-list-item/discourse-adplugin.gjs: -------------------------------------------------------------------------------- 1 | import Component from "@ember/component"; 2 | import { classNames, tagName } from "@ember-decorators/component"; 3 | import { slotContenders } from "discourse/plugins/discourse-adplugin/discourse/components/ad-slot"; 4 | import AdSlot from "../../components/ad-slot"; 5 | 6 | @tagName("tr") 7 | @classNames("after-topic-list-item-outlet", "discourse-adplugin") 8 | export default class DiscourseAdplugin extends Component { 9 | static shouldRender(args, context) { 10 | return ( 11 | args.index && 12 | slotContenders( 13 | context.site, 14 | context.siteSettings, 15 | "topic-list-between", 16 | args.index 17 | ).length > 0 18 | ); 19 | } 20 | 21 | 29 | } 30 | -------------------------------------------------------------------------------- /db/migrate/20240208195102_migrate_dfp_to_exclude_groups.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class MigrateDfpToExcludeGroups < ActiveRecord::Migration[7.0] 4 | def up 5 | dfp_display_groups_raw = 6 | DB.query_single("SELECT value FROM site_settings WHERE name = 'dfp_display_groups'").first 7 | 8 | if dfp_display_groups_raw.present? 9 | dfp_exclude_groups = 10 | case dfp_display_groups_raw 11 | when "10" 12 | "3|11|12|13|14" 13 | when "10|11" 14 | "3|12|13|14" 15 | when "10|11|12" 16 | "3|13|14" 17 | when "10|11|12|13" 18 | "3|14" 19 | when "10|11|12|14" 20 | "3" 21 | end 22 | 23 | DB.exec(<<~SQL, setting: dfp_exclude_groups) 24 | INSERT INTO site_settings(name, value, data_type, created_at, updated_at) 25 | VALUES('dfp_exclude_groups', :setting, '20', NOW(), NOW()) 26 | SQL 27 | end 28 | end 29 | 30 | def down 31 | raise ActiveRecord::IrreversibleMigration 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /db/migrate/20240208195101_migrate_amazon_to_exclude_groups.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class MigrateAmazonToExcludeGroups < ActiveRecord::Migration[7.0] 4 | def up 5 | amazon_display_groups_raw = 6 | DB.query_single("SELECT value FROM site_settings WHERE name = 'amazon_display_groups'").first 7 | 8 | if amazon_display_groups_raw.present? 9 | amazon_exclude_groups = 10 | case amazon_display_groups_raw 11 | when "10" 12 | "3|11|12|13|14" 13 | when "10|11" 14 | "3|12|13|14" 15 | when "10|11|12" 16 | "3|13|14" 17 | when "10|11|12|13" 18 | "3|14" 19 | when "10|11|12|14" 20 | "3" 21 | end 22 | 23 | DB.exec(<<~SQL, setting: amazon_exclude_groups) 24 | INSERT INTO site_settings(name, value, data_type, created_at, updated_at) 25 | VALUES('amazon_exclude_groups', :setting, '20', NOW(), NOW()) 26 | SQL 27 | end 28 | end 29 | 30 | def down 31 | raise ActiveRecord::IrreversibleMigration 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /db/migrate/20240208195103_migrate_carbon_to_exclude_groups.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class MigrateCarbonToExcludeGroups < ActiveRecord::Migration[7.0] 4 | def up 5 | carbon_display_groups_raw = 6 | DB.query_single("SELECT value FROM site_settings WHERE name = 'carbon_display_groups'").first 7 | 8 | if carbon_display_groups_raw.present? 9 | carbon_exclude_groups = 10 | case carbon_display_groups_raw 11 | when "10" 12 | "3|11|12|13|14" 13 | when "10|11" 14 | "3|12|13|14" 15 | when "10|11|12" 16 | "3|13|14" 17 | when "10|11|12|13" 18 | "3|14" 19 | when "10|11|12|14" 20 | "3" 21 | end 22 | 23 | DB.exec(<<~SQL, setting: carbon_exclude_groups) 24 | INSERT INTO site_settings(name, value, data_type, created_at, updated_at) 25 | VALUES('carbon_exclude_groups', :setting, '20', NOW(), NOW()) 26 | SQL 27 | end 28 | end 29 | 30 | def down 31 | raise ActiveRecord::IrreversibleMigration 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /admin/assets/javascripts/admin/components/house-ads-chooser.js: -------------------------------------------------------------------------------- 1 | import { computed } from "@ember/object"; 2 | import { classNames } from "@ember-decorators/component"; 3 | import { makeArray } from "discourse/lib/helpers"; 4 | import MultiSelectComponent from "select-kit/components/multi-select"; 5 | 6 | @classNames("house-ads-chooser") 7 | export default class HouseAdsChooser extends MultiSelectComponent { 8 | filterable = true; 9 | filterPlaceholder = "admin.adplugin.house_ads.filter_placeholder"; 10 | tokenSeparator = "|"; 11 | allowCreate = false; 12 | allowAny = false; 13 | settingValue = ""; 14 | valueAttribute = null; 15 | nameProperty = null; 16 | 17 | @computed("settingValue") 18 | get value() { 19 | return this.settingValue 20 | .toString() 21 | .split(this.tokenSeparator) 22 | .filter(Boolean); 23 | } 24 | 25 | computeValues() { 26 | return this.settingValue.split(this.tokenSeparator).filter(Boolean); 27 | } 28 | 29 | @computed("choices") 30 | get content() { 31 | return makeArray(this.choices); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /db/migrate/20240208195100_migrate_adsense_to_exclude_groups.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class MigrateAdsenseToExcludeGroups < ActiveRecord::Migration[7.0] 4 | def up 5 | adsense_display_groups_raw = 6 | DB.query_single("SELECT value FROM site_settings WHERE name = 'adsense_display_groups'").first 7 | 8 | if adsense_display_groups_raw.present? 9 | adsense_exclude_groups = 10 | case adsense_display_groups_raw 11 | when "10" 12 | "3|11|12|13|14" 13 | when "10|11" 14 | "3|12|13|14" 15 | when "10|11|12" 16 | "3|13|14" 17 | when "10|11|12|13" 18 | "3|14" 19 | when "10|11|12|14" 20 | "3" 21 | end 22 | 23 | DB.exec(<<~SQL, setting: adsense_exclude_groups) 24 | INSERT INTO site_settings(name, value, data_type, created_at, updated_at) 25 | VALUES('adsense_exclude_groups', :setting, '20', NOW(), NOW()) 26 | SQL 27 | end 28 | end 29 | 30 | def down 31 | raise ActiveRecord::IrreversibleMigration 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /db/migrate/20240118195156_migrate_tl_to_group_settings_dfp_through_tl.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class MigrateTlToGroupSettingsDfpThroughTl < ActiveRecord::Migration[7.0] 4 | def up 5 | dfp_through_trust_level_raw = 6 | DB.query_single( 7 | "SELECT value FROM site_settings WHERE name = 'dfp_through_trust_level'", 8 | ).first 9 | 10 | if dfp_through_trust_level_raw.present? 11 | dfp_display_groups = 12 | case dfp_through_trust_level_raw 13 | when "0" 14 | "10" 15 | when "1" 16 | "10|11" 17 | when "2" 18 | "10|11|12" 19 | when "3" 20 | "10|11|12|13" 21 | when "4" 22 | "10|11|12|13|14" 23 | end 24 | 25 | DB.exec(<<~SQL, setting: dfp_display_groups) 26 | INSERT INTO site_settings(name, value, data_type, created_at, updated_at) 27 | VALUES('dfp_display_groups', :setting, '20', NOW(), NOW()) 28 | SQL 29 | end 30 | end 31 | 32 | def down 33 | raise ActiveRecord::IrreversibleMigration 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /db/migrate/20240118195157_migrate_tl_to_group_settings_amazon_through_tl.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class MigrateTlToGroupSettingsAmazonThroughTl < ActiveRecord::Migration[7.0] 4 | def up 5 | amazon_through_trust_level_raw = 6 | DB.query_single( 7 | "SELECT value FROM site_settings WHERE name = 'amazon_through_trust_level'", 8 | ).first 9 | 10 | if amazon_through_trust_level_raw.present? 11 | amazon_display_groups = 12 | case amazon_through_trust_level_raw 13 | when "0" 14 | "10" 15 | when "1" 16 | "10|11" 17 | when "2" 18 | "10|11|12" 19 | when "3" 20 | "10|11|12|13" 21 | when "4" 22 | "10|11|12|13|14" 23 | end 24 | 25 | DB.exec(<<~SQL, setting: amazon_display_groups) 26 | INSERT INTO site_settings(name, value, data_type, created_at, updated_at) 27 | VALUES('amazon_display_groups', :setting, '20', NOW(), NOW()) 28 | SQL 29 | end 30 | end 31 | 32 | def down 33 | raise ActiveRecord::IrreversibleMigration 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /db/migrate/20240208195104_migrate_adbutler_to_exclude_groups.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class MigrateAdbutlerToExcludeGroups < ActiveRecord::Migration[7.0] 4 | def up 5 | adbutler_display_groups_raw = 6 | DB.query_single( 7 | "SELECT value FROM site_settings WHERE name = 'adbutler_display_groups'", 8 | ).first 9 | 10 | if adbutler_display_groups_raw.present? 11 | adbutler_exclude_groups = 12 | case adbutler_display_groups_raw 13 | when "10" 14 | "3|11|12|13|14" 15 | when "10|11" 16 | "3|12|13|14" 17 | when "10|11|12" 18 | "3|13|14" 19 | when "10|11|12|13" 20 | "3|14" 21 | when "10|11|12|14" 22 | "3" 23 | end 24 | 25 | DB.exec(<<~SQL, setting: adbutler_exclude_groups) 26 | INSERT INTO site_settings(name, value, data_type, created_at, updated_at) 27 | VALUES('adbutler_exclude_groups', :setting, '20', NOW(), NOW()) 28 | SQL 29 | end 30 | end 31 | 32 | def down 33 | raise ActiveRecord::IrreversibleMigration 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /db/migrate/20240118195155_migrate_tl_to_group_settings_adsense_through_tl.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class MigrateTlToGroupSettingsAdsenseThroughTl < ActiveRecord::Migration[7.0] 4 | def up 5 | adsense_through_trust_level_raw = 6 | DB.query_single( 7 | "SELECT value FROM site_settings WHERE name = 'adsense_through_trust_level'", 8 | ).first 9 | 10 | if adsense_through_trust_level_raw.present? 11 | adsense_display_groups = 12 | case adsense_through_trust_level_raw 13 | when "0" 14 | "10" 15 | when "1" 16 | "10|11" 17 | when "2" 18 | "10|11|12" 19 | when "3" 20 | "10|11|12|13" 21 | when "4" 22 | "10|11|12|13|14" 23 | end 24 | 25 | DB.exec(<<~SQL, setting: adsense_display_groups) 26 | INSERT INTO site_settings(name, value, data_type, created_at, updated_at) 27 | VALUES('adsense_display_groups', :setting, '20', NOW(), NOW()) 28 | SQL 29 | end 30 | end 31 | 32 | def down 33 | raise ActiveRecord::IrreversibleMigration 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /db/migrate/20240118195159_migrate_tl_to_group_settings_adbutler_through_tl.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class MigrateTlToGroupSettingsAdbutlerThroughTl < ActiveRecord::Migration[7.0] 4 | def up 5 | adbutler_through_trust_level_raw = 6 | DB.query_single( 7 | "SELECT value FROM site_settings WHERE name = 'adbutler_through_trust_level'", 8 | ).first 9 | 10 | if adbutler_through_trust_level_raw.present? 11 | adbutler_display_groups = 12 | case adbutler_through_trust_level_raw 13 | when "0" 14 | "10" 15 | when "1" 16 | "10|11" 17 | when "2" 18 | "10|11|12" 19 | when "3" 20 | "10|11|12|13" 21 | when "4" 22 | "10|11|12|13|14" 23 | end 24 | 25 | DB.exec(<<~SQL, setting: adbutler_display_groups) 26 | INSERT INTO site_settings(name, value, data_type, created_at, updated_at) 27 | VALUES('adbutler_display_groups', :setting, '20', NOW(), NOW()) 28 | SQL 29 | end 30 | end 31 | 32 | def down 33 | raise ActiveRecord::IrreversibleMigration 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /db/migrate/20240118195158_migrate_tl_to_group_settings_carbonads_through_tl.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class MigrateTlToGroupSettingsCarbonadsThroughTl < ActiveRecord::Migration[7.0] 4 | def up 5 | carbonads_through_trust_level_raw = 6 | DB.query_single( 7 | "SELECT value FROM site_settings WHERE name = 'carbonads_through_trust_level'", 8 | ).first 9 | 10 | if carbonads_through_trust_level_raw.present? 11 | carbonads_display_groups = 12 | case carbonads_through_trust_level_raw 13 | when "0" 14 | "10" 15 | when "1" 16 | "10|11" 17 | when "2" 18 | "10|11|12" 19 | when "3" 20 | "10|11|12|13" 21 | when "4" 22 | "10|11|12|13|14" 23 | end 24 | 25 | DB.exec(<<~SQL, setting: carbonads_display_groups) 26 | INSERT INTO site_settings(name, value, data_type, created_at, updated_at) 27 | VALUES('carbonads_display_groups', :setting, '20', NOW(), NOW()) 28 | SQL 29 | end 30 | end 31 | 32 | def down 33 | raise ActiveRecord::IrreversibleMigration 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 Discourse 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /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 | js: 9 | adplugin: 10 | advertisement_label: "آگهی" 11 | admin_js: 12 | admin: 13 | site_settings: 14 | categories: 15 | ad_plugin: "پلاگین آگهی" 16 | adsense_plugin: "AdSense" 17 | amazon_plugin: "آمازون" 18 | carbonads_plugin: "آگهی Carbon" 19 | adbutler_plugin: "AdButler" 20 | adplugin: 21 | house_ads: 22 | title: "آگهی خانه" 23 | new: "جدید" 24 | settings: "تنظیمات" 25 | new_name: "آگهی خانه جدید" 26 | save: "ذخیره" 27 | delete: "حذف" 28 | get_started: "با ایجاد یک تبلیغ جدید شروع کنید.\nچگونه تست پرژگ" 29 | filter_placeholder: "انتخاب آگهی..." 30 | more_settings: "تنظیمات بیشتر" 31 | preview: "پیش‌نمایش" 32 | post_bottom: 33 | title: "بین پست‌ها" 34 | topic_list_between: 35 | title: "بین موضوعات" 36 | -------------------------------------------------------------------------------- /admin/assets/javascripts/admin/components/house-ads-list-setting.gjs: -------------------------------------------------------------------------------- 1 | import { action } from "@ember/object"; 2 | import { mapBy } from "@ember/object/computed"; 3 | import { classNames } from "@ember-decorators/component"; 4 | import DButton from "discourse/components/d-button"; 5 | import { makeArray } from "discourse/lib/helpers"; 6 | import HouseAdsChooser from "./house-ads-chooser"; 7 | import HouseAdsSetting from "./house-ads-setting"; 8 | 9 | @classNames("house-ads-setting house-ads-list-setting") 10 | export default class HouseAdsListSetting extends HouseAdsSetting { 11 | @mapBy("allAds", "name") adNames; 12 | 13 | @action 14 | changeAdValue(value) { 15 | const settingValue = makeArray(value).join("|"); 16 | this.set("adValue", settingValue); 17 | } 18 | 19 | 34 | } 35 | -------------------------------------------------------------------------------- /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 | js: 9 | adplugin: 10 | advertisement_label: "PUBLICITATE" 11 | admin_js: 12 | admin: 13 | site_settings: 14 | categories: 15 | ad_plugin: "Ad Plugin" 16 | adsense_plugin: "AdSense" 17 | amazon_plugin: "Amazon" 18 | carbonads_plugin: "Carbon Ads" 19 | adbutler_plugin: "AdButler" 20 | adplugin: 21 | house_ads: 22 | title: "House Ads" 23 | new: "Nou" 24 | settings: "Setări" 25 | save: "Salvează" 26 | delete: "Șterge" 27 | get_started: "Începe prin a crea un anunț nou." 28 | filter_placeholder: "Selectează reclame..." 29 | more_settings: "Mai multe setări" 30 | category_chooser_description: "Alege categoriile în care trebuie afișat acest anunț sau lasă gol pentru a afișa anunțul peste tot. Setarea site-ului `no_ads_for_categories` are prioritate față de această setare." 31 | group_chooser_description: "Alege grupurile care pot vizualiza acest anunț sau lasă gol pentru a afișa anunțul tuturor utilizatorilor conectați." 32 | preview: "Previzualizează" 33 | -------------------------------------------------------------------------------- /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 | js: 9 | adplugin: 10 | advertisement_label: "廣告" 11 | admin_js: 12 | admin: 13 | site_settings: 14 | categories: 15 | ad_plugin: "廣告插件" 16 | adsense_plugin: "AdSense" 17 | amazon_plugin: "Amazon" 18 | carbonads_plugin: "Carbon 廣告" 19 | adplugin: 20 | house_ads: 21 | new: "新使用者" 22 | settings: "設定" 23 | save: "儲存" 24 | delete: "刪除" 25 | filter_placeholder: "選擇廣告..." 26 | more_settings: "更多設置" 27 | preview: "預覽" 28 | topic_list_top: 29 | title: "主題列表頂部廣告" 30 | description: "顯示在主題列表頁面頂部的廣告。" 31 | topic_above_post_stream: 32 | title: "帖子流上方的主題" 33 | description: "顯示在主題頁面上主題標題上方的廣告。" 34 | topic_above_suggested: 35 | title: "上面建議的話題" 36 | description: "在主題的最後一篇文章之後、建議主題上方顯示的廣告。" 37 | post_bottom: 38 | title: "帖子之間" 39 | description: "在每 N 個帖子之後顯示在帖子之間的廣告。" 40 | topic_list_between: 41 | title: "話題之間" 42 | description: "在主題之間、每 N 個主題之後展示的廣告。" 43 | -------------------------------------------------------------------------------- /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 | site_settings: 9 | adsense_topic_list_top_ad_sizes: " reklaami suurus" 10 | adsense_mobile_topic_list_top_ad_size: "Vali oma reklaami suurus" 11 | adsense_topic_above_post_stream_ad_sizes: "Vali oma reklaami suurus" 12 | adsense_mobile_topic_above_post_stream_ad_size: "Vali oma reklaami suurus" 13 | adsense_topic_above_suggested_ad_sizes: "Vali oma reklaami suurus" 14 | adsense_mobile_topic_above_suggested_ad_size: "Vali oma reklaami suurus" 15 | adsense_post_bottom_ad_sizes: "Vali oma reklaami suurus" 16 | adsense_mobile_post_bottom_ad_size: "Vali oma reklaami suurus" 17 | amazon_topic_list_top_ad_width_code: "Sisesta oma reklaami laius" 18 | amazon_topic_list_top_ad_height_code: "Sisesta oma reklaami kõrgus" 19 | amazon_topic_above_post_stream_ad_width_code: "Sisesta oma reklaami laius" 20 | amazon_topic_above_post_stream_ad_height_code: "Sisesta oma reklaami kõrgus" 21 | amazon_topic_above_suggested_ad_width_code: "Sisesta oma reklaami laius" 22 | amazon_topic_above_suggested_ad_height_code: "Sisesta oma reklaami kõrgus" 23 | amazon_post_bottom_ad_width_code: "Sisesta oma reklaami laius" 24 | amazon_post_bottom_ad_height_code: "Sisesta oma reklaami kõrgus" 25 | -------------------------------------------------------------------------------- /spec/system/admin_house_ad_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | describe "Admin House Ad", type: :system do 4 | fab!(:admin) 5 | let(:house_ad) do 6 | AdPlugin::HouseAd.create( 7 | name: "some-name", 8 | html: "
somecode
", 9 | visible_to_anons: true, 10 | visible_to_logged_in_users: false, 11 | ) 12 | end 13 | 14 | before do 15 | enable_current_plugin 16 | sign_in(admin) 17 | end 18 | 19 | describe "when visiting the page for creating new ads" do 20 | it "has the visibility checkboxes on by default" do 21 | visit("/admin/plugins/pluginad/house_creatives/new") 22 | 23 | expect(find("input.visible-to-anonymous-checkbox").checked?).to eq(true) 24 | expect(find("input.visible-to-logged-in-checkbox").checked?).to eq(true) 25 | end 26 | end 27 | 28 | describe "when visiting the page of an existing ad" do 29 | it "the controls reflect the correct state of the ad" do 30 | visit("/admin/plugins/pluginad/house_creatives/#{house_ad.id}") 31 | 32 | expect(find("input.house-ad-name").value).to eq(house_ad.name) 33 | expect(find("input.visible-to-anonymous-checkbox").checked?).to eq(true) 34 | expect(find("input.visible-to-logged-in-checkbox").checked?).to eq(false) 35 | # would be nice to assert for the HTML content in ace-editor, but there 36 | # doesn't seem to be a way to check the content in ace-editor from the 37 | # DOM 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /assets/javascripts/discourse/components/carbonads-ad.gjs: -------------------------------------------------------------------------------- 1 | import { htmlSafe } from "@ember/template"; 2 | import discourseComputed from "discourse/lib/decorators"; 3 | import AdComponent from "./ad-component"; 4 | 5 | export default class CarbonadsAd extends AdComponent { 6 | serve_id = null; 7 | placement = null; 8 | 9 | init() { 10 | this.set("serve_id", this.siteSettings.carbonads_serve_id); 11 | this.set("placement", this.siteSettings.carbonads_placement); 12 | super.init(); 13 | } 14 | 15 | @discourseComputed("serve_id", "placement") 16 | url(serveId, placement) { 17 | return htmlSafe( 18 | `//cdn.carbonads.com/carbon.js?serve=${serveId}&placement=${placement}` 19 | ); 20 | } 21 | 22 | @discourseComputed 23 | showCarbonAds() { 24 | if (!this.currentUser) { 25 | return true; 26 | } 27 | 28 | return this.currentUser.show_carbon_ads; 29 | } 30 | 31 | @discourseComputed( 32 | "placement", 33 | "serve_id", 34 | "showCarbonAds", 35 | "showToGroups", 36 | "showOnCurrentPage" 37 | ) 38 | showAd(placement, serveId, showCarbonAds, showToGroups, showOnCurrentPage) { 39 | return ( 40 | placement && serveId && showCarbonAds && showToGroups && showOnCurrentPage 41 | ); 42 | } 43 | 44 | 51 | } 52 | -------------------------------------------------------------------------------- /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 | js: 9 | adplugin: 10 | advertisement_label: "광고" 11 | admin_js: 12 | admin: 13 | site_settings: 14 | categories: 15 | ad_plugin: "광고 플러그인" 16 | dfp_plugin: "DFP/Ad 관리자" 17 | adsense_plugin: "애드센스" 18 | amazon_plugin: "Amazon" 19 | carbonads_plugin: "카본 광고" 20 | adbutler_plugin: "AdButler" 21 | adplugin: 22 | house_ads: 23 | title: "하우스 광고" 24 | new: "새값" 25 | settings: "설정" 26 | new_name: "새 집 광고" 27 | save: "저장" 28 | delete: "삭제" 29 | description: "자신의 광고와 광고를 게재 할 위치를 정의하십시오." 30 | get_started: "새 광고를 만들어 시작하십시오." 31 | filter_placeholder: "광고 선택 ..." 32 | more_settings: "자세한 설정" 33 | preview: "미리 보기" 34 | topic_list_top: 35 | title: "주제 목록 인기 광고" 36 | description: "주제 목록 페이지 상단에 게재 할 광고" 37 | topic_above_post_stream: 38 | title: "포스트 스트림 위의 주제" 39 | description: "주제 페이지에서 주제 제목 위에 게재되는 광고" 40 | topic_above_suggested: 41 | title: "위의 주제 제안" 42 | description: "제안 된 주제 위에 주제의 마지막 게시물 이후에 게재 할 광고입니다." 43 | post_bottom: 44 | title: "게시물 사이" 45 | description: "N 개의 게시물마다 게시물 사이에 광고가 게재됩니다." 46 | -------------------------------------------------------------------------------- /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 | js: 9 | adplugin: 10 | advertisement_label: "โฆษณา" 11 | admin_js: 12 | admin: 13 | site_settings: 14 | categories: 15 | ad_plugin: "ปลั๊กอินโฆษณา" 16 | dfp_plugin: "DFP/ตัวจัดการโฆษณา" 17 | adsense_plugin: "AdSense" 18 | amazon_plugin: "อเมซอน" 19 | adplugin: 20 | house_ads: 21 | new: "ใหม่" 22 | settings: "การตั้งค่า" 23 | save: "บันทึก" 24 | delete: "ลบ" 25 | description: "กำหนดโฆษณาของคุณเองและตำแหน่งที่ควรแสดง" 26 | get_started: "เริ่มต้นด้วยการสร้างโฆษณาใหม่" 27 | filter_placeholder: "เลือกโฆษณา ..." 28 | more_settings: "การตั้งค่าเพิ่มเติม" 29 | preview: "แสดงตัวอย่าง" 30 | topic_list_top: 31 | title: "หัวข้อรายการโฆษณายอดนิยม" 32 | description: "โฆษณาที่จะแสดงที่ด้านบนสุดของหน้ารายการหัวข้อ" 33 | topic_above_post_stream: 34 | title: "หัวข้อด้านบนโพสต์สตรีม" 35 | description: "โฆษณาที่จะแสดงเหนือชื่อหัวข้อในหน้าหัวข้อ" 36 | topic_above_suggested: 37 | description: "โฆษณาที่จะแสดงหลังโพสต์ล่าสุดในหัวข้อ เหนือหัวข้อที่แนะนำ" 38 | post_bottom: 39 | title: "ระหว่างโพสต์" 40 | description: "โฆษณาที่จะแสดงระหว่างโพสต์หลังจากทุกๆ N โพสต์" 41 | -------------------------------------------------------------------------------- /admin/assets/javascripts/admin/templates/plugins-house-ads.gjs: -------------------------------------------------------------------------------- 1 | import { LinkTo } from "@ember/routing"; 2 | import RouteTemplate from "ember-route-template"; 3 | import icon from "discourse/helpers/d-icon"; 4 | import { i18n } from "discourse-i18n"; 5 | 6 | export default RouteTemplate( 7 | 43 | ); 44 | -------------------------------------------------------------------------------- /spec/requests/house_ad_settings_controller_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | describe AdPlugin::HouseAdSettingsController do 4 | let(:admin) { Fabricate(:admin) } 5 | 6 | before do 7 | enable_current_plugin 8 | AdPlugin::HouseAd.create(name: "Banner", html: "

Banner

") 9 | end 10 | 11 | describe "update" do 12 | let(:valid_params) { { value: "Banner" } } 13 | 14 | it "error if not logged in" do 15 | put "/admin/plugins/pluginad/house_settings/topic_list_top.json", params: valid_params 16 | expect(response.status).to eq(404) 17 | end 18 | 19 | it "error if not staff" do 20 | sign_in(Fabricate(:user)) 21 | put "/admin/plugins/pluginad/house_settings/topic_list_top.json", params: valid_params 22 | expect(response.status).to eq(404) 23 | end 24 | 25 | context "when logged in as admin" do 26 | before { sign_in(admin) } 27 | 28 | it "changes the setting" do 29 | put "/admin/plugins/pluginad/house_settings/topic_list_top.json", params: valid_params 30 | expect(response.status).to eq(200) 31 | expect(AdPlugin::HouseAdSetting.all[:topic_list_top]).to eq(valid_params[:value]) 32 | end 33 | 34 | it "errors on invalid setting name" do 35 | put "/admin/plugins/pluginad/house_settings/nope-nope.json", params: valid_params 36 | expect(response.status).to eq(404) 37 | end 38 | 39 | it "errors on invalid setting value" do 40 | put "/admin/plugins/pluginad/house_settings/topic_list_top.json", 41 | params: valid_params.merge(value: "Banner|