Commits (7)
......@@ -13,17 +13,18 @@
"color-highlight.markerType": "dot-before"
},
"extensions": [
"mikestead.dotenv",
"bmewburn.vscode-intelephense-client",
"streetsidesoftware.code-spell-checker",
"naumovs.color-highlight",
"heybourn.headwind",
"wayou.vscode-todo-highlight",
"esbenp.prettier-vscode",
"bradlc.vscode-tailwindcss",
"jamesbirtles.svelte-vscode",
"dbaeumer.vscode-eslint",
"stylelint.vscode-stylelint",
"wongjn.php-sniffer"
]
"mikestead.dotenv",
"bmewburn.vscode-intelephense-client",
"streetsidesoftware.code-spell-checker",
"naumovs.color-highlight",
"heybourn.headwind",
"wayou.vscode-todo-highlight",
"esbenp.prettier-vscode",
"bradlc.vscode-tailwindcss",
"jamesbirtles.svelte-vscode",
"dbaeumer.vscode-eslint",
"stylelint.vscode-stylelint",
"wongjn.php-sniffer",
"eamodio.gitlens"
]
}
......@@ -2,7 +2,7 @@
# Example Environment Configuration file
#
# This file can be used as a starting point for
# your castopod instance settings.
# your Castopod Host instance settings.
#
# For manual configuration:
# - copy this file's contents to a file named `.env`
......@@ -10,19 +10,34 @@
# - go to `/cp-install` to complete installation
#--------------------------------------------------------------------
#--------------------------------------------------------------------
# Instance configuration
#--------------------------------------------------------------------
app.baseURL="https://YOUR_DOMAIN_NAME/"
app.mediaBaseURL="https://YOUR_MEDIA_DOMAIN_NAME/"
app.adminGateway="cp-admin"
app.authGateway="cp-auth"
#--------------------------------------------------------------------
# Database configuration
#--------------------------------------------------------------------
database.default.hostname="localhost"
database.default.database="castopod"
database.default.username="root"
database.default.password="****"
database.default.DBPrefix="cp_"
#--------------------------------------------------------------------
# Cache configuration (advanced)
#
# Keep as is if you don't know what this means
#--------------------------------------------------------------------
cache.handler="file"
# Redis configuration
#--------------------------------------------------------------------
# cache.handler="redis"
# cache.redis.host="127.0.0.1"
# cache.redis.password=null
# cache.redis.port=6379
# cache.redis.database=0
......@@ -167,7 +167,7 @@ mariadb
phpmyadmin
sessions
# Castopod bundle & packages
castopod/
castopod-*.zip
castopod-*.tar.gz
# Castopod Host bundle & packages
castopod-host/
castopod-host-*.zip
castopod-host-*.tar.gz
......@@ -48,11 +48,11 @@ bundle_app:
- mv ./writable/uploads/GeoLite2-City* ./writable/uploads/GeoLite2-City
# create bundle folder: uses .rsync-filter (-F) file to copy only needed files
- rsync -aF --progress . ./castopod
- rsync -aF --progress . ./castopod-host
artifacts:
name: "castopod-${CI_COMMIT_REF_SLUG}_${CI_COMMIT_SHORT_SHA}"
name: "castopod-host-${CI_COMMIT_REF_SLUG}_${CI_COMMIT_SHORT_SHA}"
paths:
- castopod
- castopod-host
except:
- main
- beta
......
<?xml version="1.0"?>
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Castopod">
<description>Castopod's coding standard based on the PSR-1 standard.</description>
<description>Castopod Host's coding standard based on the PSR-1 standard.</description>
<!-- Include the whole PSR-1 standard -->
<rule ref="PSR1"/>
......
......@@ -33,12 +33,12 @@
"gitlabUrl": "https://code.podlibre.org/",
"assets": [
{
"path": "castopod-*.zip",
"label": "Castopod Package (zip)"
"path": "castopod-host-*.zip",
"label": "Castopod Host Package (zip)"
},
{
"path": "castopod-*.tar.gz",
"label": "Castopod Package (tar.gz)"
"path": "castopod-host-*.tar.gz",
"label": "Castopod Host Package (tar.gz)"
}
]
}
......
# rsync filter rules to copy required files for Castopod's bundle
# rsync filter rules to copy required files for Castopod Host's bundle
- app/Views/_assets/
+ app/***
......
# [1.0.0-alpha.54](https://code.podlibre.org/podlibre/castopod-host/compare/v1.0.0-alpha.53...v1.0.0-alpha.54) (2021-05-03)
### Features
* set app parameter forceGlobalSecureRequests = true forcing requests to go through https ([d9dff1b](https://code.podlibre.org/podlibre/castopod-host/commit/d9dff1b8bf89c8b526ad6cb89f98a1f160d49117))
* **ux:** remove admin dashboard and redirect directly to podcast list ([27c48b8](https://code.podlibre.org/podlibre/castopod-host/commit/27c48b8fa930b33e5e15f0c8685e468e857ca9cd))
* add cache to ActivityPub sql queries + cache activity and note pages ([2d297f4](https://code.podlibre.org/podlibre/castopod-host/commit/2d297f45b3d7ef6e8711875a0b9b908e878115fa))
### Performance Improvements
* **cache:** update CI4 to use cache's deleteMatching method ([54b84f9](https://code.podlibre.org/podlibre/castopod-host/commit/54b84f96843af13f579fea49102c8c2ef81b0a54))
* **docker:** add redis caching service for development ([05ace8c](https://code.podlibre.org/podlibre/castopod-host/commit/05ace8cff2ef02d19abd40097ac5546dca6a54ca))
# [1.0.0-alpha.53](https://code.podlibre.org/podlibre/castopod/compare/v1.0.0-alpha.52...v1.0.0-alpha.53) (2021-04-16)
......
# Contributing to Castopod
# Contributing to Castopod Host
Love Castopod and want to help? Thanks so much, there's something to do for
Love Castopod Host and want to help? Thanks so much, there's something to do for
everybody!
Please take a moment to review this document in order to make the contribution
......@@ -11,10 +11,14 @@ developers managing and developing this open source project. In return, they
should reciprocate that respect in addressing your issue or assessing patches
and features.
⚠️ Note that **any** contribution made on a repository other than
[the original repository](https://code.podlibre.org/podlibre/castopod-host) will
not be accepted.
## Using the issue tracker
The [issue tracker](https://code.podlibre.org/podlibre/castopod/-/issues) is the
preferred channel for [bug reports](#bug-reports),
The [issue tracker](https://code.podlibre.org/podlibre/castopod-host/-/issues)
is the preferred channel for [bug reports](#bug-reports),
[features requests](#feature-requests) and
[submitting pull requests](#pull-requests).
......@@ -73,13 +77,13 @@ the project:
```bash
# Clone your fork of the repo into the current directory
git clone https://code.podlibre.org/<your-username>/castopod.git
git clone https://code.podlibre.org/<your-username>/castopod-host.git
# Navigate to the newly cloned directory
cd castopod
cd castopod-host
# Assign the original repo to a remote called "upstream"
git remote add upstream https://code.podlibre.org/podlibre/castopod.git
git remote add upstream https://code.podlibre.org/podlibre/castopod-host.git
```
2. If you cloned a while ago, get the latest changes from upstream:
......@@ -119,7 +123,7 @@ git push origin <topic-branch-name>
**IMPORTANT**: By submitting a patch, you agree to allow the project owners to
license your work under the terms of the
[GNU AGPLv3](https://code.podlibre.org/podlibre/castopod/-/blob/main/LICENSE).
[GNU AGPLv3](https://code.podlibre.org/podlibre/castopod-host/-/blob/main/LICENSE).
## Collaborating guidelines
......
# Castopod dependencies
# Castopod Host dependencies
Castopod uses the following components:
Castopod Host uses the following components:
PHP Dependencies:
......
FROM php:7.3-fpm
COPY . /castopod
WORKDIR /castopod
COPY . /castopod-host
WORKDIR /castopod-host
### Install CodeIgniter's server requirements
#-- https://github.com/codeigniter4/appstarter#server-requirements
......@@ -17,6 +17,10 @@ RUN apt-get update && apt-get install -y \
RUN docker-php-ext-configure gd --with-jpeg-dir=/usr/include/ \
&& docker-php-ext-install gd
RUN pecl install -o -f redis \
&& rm -rf /tmp/pear \
&& docker-php-ext-enable redis
RUN docker-php-ext-install mysqli && docker-php-ext-enable mysqli
RUN echo "file_uploads = On\n" \
......@@ -30,4 +34,4 @@ RUN echo "file_uploads = On\n" \
RUN apt-get update && \
apt-get install -y cron
RUN crontab /castopod/crontab
RUN crontab /castopod-host/crontab
# How to install Castopod <!-- omit in toc -->
# How to install Castopod Host <!-- omit in toc -->
Castopod was thought to be easy to install. Whether using dedicated or shared
hosting, you can install it on most PHP-MySQL compatible web servers.
_Castopod Host_ was thought-out to be easy to install. Whether using dedicated
or shared hosting, you can install it on most PHP-MySQL compatible web servers.
## Table of contents <!-- omit in toc -->
- [Install instructions](#install-instructions)
- [(optional) Manual configuration](#optional-manual-configuration)
- [0. Pre-requisites](#0-pre-requisites)
- [1. Install Wizard](#1-install-wizard)
- [1-alt Manual configuration](#1-alt-manual-configuration)
- [Web Server Requirements](#web-server-requirements)
- [PHP v7.3 or higher](#php-v73-or-higher)
- [MySQL compatible database](#mysql-compatible-database)
......@@ -16,33 +18,44 @@ hosting, you can install it on most PHP-MySQL compatible web servers.
## Install instructions
0. Create a MySQL database for Castopod with a user having access and
### 0. Pre-requisites
0. Get a Web Server with requirements installed
1. Create a MySQL database for Castopod Host with a user having access and
modification privileges (for more info, see
[Web Server Requirements](#web-server-requirements)).
1. Download and unzip the Castopod package onto the web server if you haven’t
already.
2. Activate HTTPS on your domain with an _SSL certificate_.
3. Download and unzip the latest
[Castopod Host Package](https://code.podlibre.org/podlibre/castopod-host/-/releases)
onto the web server if you haven’t already.
- ⚠️ Set the web server document root to the `public/` sub-folder.
2. ⚠️ For broadcasting social activities to the fediverse, add a cron task on
your web server to run every minute (replace the paths accordingly):
4. Add a cron task on your web server to run every minute (replace the paths
accordingly):
```php
* * * * * /path/to/php /path/to/castopod/public/index.php scheduled-activities
* * * * * /path/to/php /path/to/castopod-host/public/index.php scheduled-activities
```
3. Run the Castopod install script by going to the install wizard page
(`https://your_domain_name.com/cp-install`) in your favorite web browser.
4. Follow the instructions on your screen.
> ⚠️ Social features will not work properly if you do not set the task. It is
> used to broadcast social activities to the fediverse.
All done, start podcasting!
### 1. Install Wizard
### (optional) Manual configuration
1. Run the Castopod Host install script by going to the install wizard page
(`https://your_domain_name.com/cp-install`) in your favorite web browser.
2. Follow the instructions on your screen.
3. Start podcasting!
Before uploading Castopod files to your web server:
### 1-alt Manual configuration
The install script writes a `.env` file in the package root. If you cannot go
through the install wizard, you can create and update the `.env` file yourself:
1. Rename the `.env.example` file to `.env` and update the default values with
your own.
2. Upload the Castopod files with `.env`
2. Upload the `.env` file to the Castopod Host Package root on your server.
3. Go to `/cp-install` to finish the install process.
4. Start podcasting!
## Web Server Requirements
......@@ -50,43 +63,48 @@ Before uploading Castopod files to your web server:
PHP version 7.3 or higher is required, with the following extensions installed:
- [intl](http://php.net/manual/en/intl.requirements.php)
- [libcurl](http://php.net/manual/en/curl.requirements.php)
- [mbstring](http://php.net/manual/en/mbstring.installation.php)
- [intl](https://php.net/manual/en/intl.requirements.php)
- [libcurl](https://php.net/manual/en/curl.requirements.php)
- [mbstring](https://php.net/manual/en/mbstring.installation.php)
- [gd](https://www.php.net/manual/en/image.installation.php)
Additionally, make sure that the following extensions are enabled in your PHP:
- json (enabled by default - don't turn it off)
- xml (enabled by default - don't turn it off)
- [mysqlnd](http://php.net/manual/en/mysqlnd.install.php)
- [mysqlnd](https://php.net/manual/en/mysqlnd.install.php)
### MySQL compatible database
> We recommend using [MariaDB](https://mariadb.org)
> We recommend using [MariaDB](https://mariadb.org).
You will need the server hostname, database name, username and password to
complete the installation process. If you do not have these, please contact your
server administrator.
> NB. Castopod Host only works with supported MySQL compatible databases. It
> will break with MySQL v5.6 for example as its end of life was on February
> 5, 2021.
#### Privileges
User must have at least these privileges on the database for Castopod to work:
`ALTER`, `DELETE`, `EXECUTE`, `INDEX`, `INSERT`, `SELECT`, `UPDATE`.
User must have at least these privileges on the database for Castopod Host to
work: `ALTER`, `DELETE`, `EXECUTE`, `INDEX`, `INSERT`, `SELECT`, `UPDATE`.
### (Optional) Other recommendations
- Redis for better cache performances.
- CDN for better performances.
- CDN for static files caching and better performances.
- e-mail gateway for lost passwords.
## Security concerns
Castopod is built on top of Codeigniter, a PHP framework that encourages
Castopod Host is built on top of Codeigniter, a PHP framework that encourages
[good security practices](https://codeigniter.com/user_guide/concepts/security.html).
To maximize your instance safety and prevent any malicious attack, we recommend
you update all your Castopod files permissions (after installation to avoid any
permission error):
you update all your Castopod Host files permissions after installation (to avoid
any permission error):
- `writable/` folder must be **readable** and **writable**.
- `public/media/` folder must be **readable** and **writable**.
......@@ -96,7 +114,7 @@ For instance, if you are using Apache or NGINX with Ubuntu you may do the
following:
```bash
sudo chown -R root:root /path/to/castopod
sudo chown -R www-data:www-data /path/to/castopod/writable
sudo chown -R www-data:www-data /path/to/castopod/public/media
sudo chown -R root:root /path/to/castopod-host
sudo chown -R www-data:www-data /path/to/castopod-host/writable
sudo chown -R www-data:www-data /path/to/castopod-host/public/media
```
# ![Castopod Logo](https://podlibre.org/static/images/Castopod-Title.svg)
# ![Castopod Host](https://podlibre.org/static/images/Castopod-Title.svg)
Castopod is an open-source podcast hosting solution for everyone.\
Whether you are a beginner, an amateur or a professional, you will get everything
you need:\
Create, upload, publish, and get comprehensive audience measurement that
respects your listeners privacy.
_Castopod Host_ is a free and open-source podcast hosting solution made for
podcasters who want engage and interact with their audience.
Castopod is a free and open-source solution (AGPL v3).\
Whether you choose to install it on your own server or have it hosted by a professional,
all your data and analytics belong to you and you only.
Create, upload, publish, interact with your followers and get comprehensive
audience measurements that respect your listeners privacy.
![Castopod Logo](https://podlibre.org/static/images/Castopod-Mascot-Server.svg)
Whether you choose to install it on your own server or have it hosted by a
professional, all your data and analytics belong to you and you only!
## Installation
![Castopod Mascot](https://podlibre.org/static/images/Castopod-Mascot-Server.svg)
You may find Castopod Host's source code on the
[original repository](https://code.podlibre.org/podlibre/castopod-host) or,
alternatively, on the
[github repository (mirror)](https://github.com/podlibre/castopod-host).
Castopod can be hosted on any PHP/MySQL server:\
Unzip it and you are ready to broadcast.
## Installation
To install Castopod on your server:
To install Castopod Host on your PHP/MySQL server:
- Download
[Castopod latest Package (zip or tar.gz)](https://code.podlibre.org/podlibre/castopod/-/releases),
- Follow the procedure “[How to install Castopod](./INSTALL.md)”.
[Castopod Host's latest Package (zip or tar.gz)](https://code.podlibre.org/podlibre/castopod-host/-/releases),
- Follow the procedure on [How to install Castopod Host](./INSTALL.md)”.
## Documentation
You can check castopod's documentation for
You can check Castopod Host's documentation for
[setting up a development environment](./docs/setup-development.md).
## Contributing
Love Castopod Host and would like to help? Check out the
[contribution guidelines](./CONTRIBUTING.md) for this project, everything should
be there!
⚠️ Note that **any** contribution made on a repository other than
[the original repository](https://code.podlibre.org/podlibre/castopod-host) will
not be accepted.
## Support
You may reach us for help or ask any question you have on:
- [Discord](https://castopod.org/discord) (for direct interaction with
developers and the community)
Alternatively, you can follow us on social media platforms to get news about
Castopod:
- [podlibre.social](https://podlibre.social/@Castopod) (Mastodon instance)
- [Twitter](https://twitter.com/castopod)
- [Facebook](https://www.facebook.com/castopod)
## Sponsors
[Castopod](https://nlnet.nl/project/Castopod/) was funded through the
[NGI0 Discovery](https://nlnet.nl/discovery/) Fund, a fund established by NLnet
with financial support from the European Commission's
[Next Generation Internet](https://www.ngi.eu/) programme, under the aegis of DG
Communications Networks, Content and Technology under grant agreement No 825322.
[NGI0 Discovery](https://nlnet.nl/discovery/) Fund under grant agreement
Nº 825322.
The fund was established by NLnet with financial support from the European
Commission's [Next Generation Internet](https://www.ngi.eu/) programme, under
the aegis of DG Communications Networks, Content and Technology.
......@@ -39,14 +39,15 @@ class PermissionModel extends \Myth\Auth\Authorization\PermissionModel
*/
public function getPermissionsForGroup(int $groupId): array
{
if (!($found = cache("group{$groupId}_permissions"))) {
$cacheName = "group{$groupId}_permissions";
if (!($found = cache($cacheName))) {
$groupPermissions = $this->db
->table('auth_groups_permissions')
->select('id, auth_permissions.name')
->join(
'auth_permissions',
'auth_permissions.id = permission_id',
'inner'
'inner',
)
->where('group_id', $groupId)
->get()
......@@ -57,7 +58,7 @@ class PermissionModel extends \Myth\Auth\Authorization\PermissionModel
$found[$row->id] = strtolower($row->name);
}
cache()->save("group{$groupId}_permissions", $found, 300);
cache()->save($cacheName, $found, 300);
}
return $found;
......
......@@ -148,7 +148,7 @@ class App extends BaseConfig
*
* @var boolean
*/
public $forceGlobalSecureRequests = false;
public $forceGlobalSecureRequests = true;
/**
* --------------------------------------------------------------------------
......@@ -253,6 +253,8 @@ class App extends BaseConfig
* Set a cookie name prefix if you need to avoid collisions.
*
* @var string
*
* @deprecated use Config\Cookie::$prefix property instead.
*/
public $cookiePrefix = '';
......@@ -264,6 +266,8 @@ class App extends BaseConfig
* Set to `.your-domain.com` for site-wide cookies.
*
* @var string
*
* @deprecated use Config\Cookie::$domain property instead.
*/
public $cookieDomain = '';
......@@ -275,6 +279,8 @@ class App extends BaseConfig
* Typically will be a forward slash.
*
* @var string
*
* @deprecated use Config\Cookie::$path property instead.
*/
public $cookiePath = '/';
......@@ -286,19 +292,23 @@ class App extends BaseConfig
* Cookie will only be set if a secure HTTPS connection exists.
*
* @var boolean
*
* @deprecated use Config\Cookie::$secure property instead.
*/
public $cookieSecure = false;
/**
* --------------------------------------------------------------------------
* Cookie HTTP Only
* Cookie HttpOnly
* --------------------------------------------------------------------------
*
* Cookie will only be accessible via HTTP(S) (no JavaScript).
*
* @var boolean
*
* @deprecated use Config\Cookie::$httponly property instead.
*/
public $cookieHTTPOnly = false;
public $cookieHTTPOnly = true;
/**
* --------------------------------------------------------------------------
......@@ -311,11 +321,18 @@ class App extends BaseConfig
* - Strict
* - ''
*
* Alternatively, you can use the constant names:
* - `Cookie::SAMESITE_NONE`
* - `Cookie::SAMESITE_LAX`
* - `Cookie::SAMESITE_STRICT`
*
* Defaults to `Lax` for compatibility with modern browsers. Setting `''`
* (empty string) means no SameSite attribute will be set on cookies. If
* set to `None`, `$cookieSecure` must also be set.
* (empty string) means default SameSite attribute set by browsers (`Lax`)
* will be set on cookies. If set to `None`, `$cookieSecure` must also be set.
*
* @var string
*
* @var string 'Lax'|'None'|'Strict'
* @deprecated use Config\Cookie::$samesite property instead.
*/
public $cookieSameSite = 'Lax';
......
......@@ -9,7 +9,7 @@
|
| NOTE: this constant is updated upon release with Continuous Integration.
*/
defined('CP_VERSION') || define('CP_VERSION', '1.0.0-alpha.53');
defined('CP_VERSION') || define('CP_VERSION', '1.0.0-alpha.54');
/*
| --------------------------------------------------------------------
......
<?php
namespace Config;
use CodeIgniter\Config\BaseConfig;
use DateTimeInterface;
class Cookie extends BaseConfig
{
/**
* --------------------------------------------------------------------------
* Cookie Prefix
* --------------------------------------------------------------------------
*
* Set a cookie name prefix if you need to avoid collisions.
*
* @var string
*/
public $prefix = '';
/**
* --------------------------------------------------------------------------
* Cookie Expires Timestamp
* --------------------------------------------------------------------------
*
* Default expires timestamp for cookies. Setting this to `0` will mean the
* cookie will not have the `Expires` attribute and will behave as a session
* cookie.
*
* @var DateTimeInterface|integer|string
*/
public $expires = 0;
/**
* --------------------------------------------------------------------------
* Cookie Path
* --------------------------------------------------------------------------
*
* Typically will be a forward slash.
*
* @var string
*/
public $path = '/';
/**
* --------------------------------------------------------------------------
* Cookie Domain
* --------------------------------------------------------------------------
*
* Set to `.your-domain.com` for site-wide cookies.
*
* @var string
*/
public $domain = '';
/**
* --------------------------------------------------------------------------
* Cookie Secure
* --------------------------------------------------------------------------
*
* Cookie will only be set if a secure HTTPS connection exists.
*
* @var boolean
*/
public $secure = false;
/**
* --------------------------------------------------------------------------
* Cookie HTTPOnly
* --------------------------------------------------------------------------
*
* Cookie will only be accessible via HTTP(S) (no JavaScript).
*
* @var boolean
*/
public $httponly = true;
/**
* --------------------------------------------------------------------------
* Cookie SameSite
* --------------------------------------------------------------------------
*
* Configure cookie SameSite setting. Allowed values are:
* - None
* - Lax
* - Strict
* - ''
*
* Alternatively, you can use the constant names:
* - `Cookie::SAMESITE_NONE`
* - `Cookie::SAMESITE_LAX`
* - `Cookie::SAMESITE_STRICT`
*
* Defaults to `Lax` for compatibility with modern browsers. Setting `''`
* (empty string) means default SameSite attribute set by browsers (`Lax`)
* will be set on cookies. If set to `None`, `$secure` must also be set.
*
* @var string
*/
public $samesite = 'Lax';
/**
* --------------------------------------------------------------------------
* Cookie Raw
* --------------------------------------------------------------------------
*
* This flag allows setting a "raw" cookie, i.e., its name and value are
* not URL encoded using `rawurlencode()`.
*
* If this is set to `true`, cookie names should be compliant of RFC 2616's
* list of allowed characters.
*
* @var boolean
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#attributes
* @see https://tools.ietf.org/html/rfc2616#section-2.2
*/
public $raw = false;
}
......@@ -81,6 +81,10 @@ Events::on('on_note_add', function ($note) {
->where('id', $note->episode_id)
->increment('notes_total');
}
// Removing all of the podcast pages is a bit overkill, but works perfectly
// same for other events below
cache()->deleteMatching("page_podcast#{$note->actor->podcast->id}*");
});
Events::on('on_note_remove', function ($note) {
......@@ -97,6 +101,9 @@ Events::on('on_note_remove', function ($note) {
->where('id', $note->episode_id)
->decrement('favourites_total', $note->favourites_count);
}
cache()->deleteMatching("page_podcast#{$note->actor->podcast->id}*");
cache()->deleteMatching("page_note#{$note->id}*");
});
Events::on('on_note_reblog', function ($actor, $note) {
......@@ -109,10 +116,18 @@ Events::on('on_note_reblog', function ($actor, $note) {
->where('id', $episodeId)
->increment('notes_total');
}
cache()->deleteMatching("page_podcast#{$note->actor->podcast->id}*");
cache()->deleteMatching("page_note#{$note->id}*");
if ($actor->is_podcast) {
cache()->deleteMatching("page_podcast#{$actor->podcast->id}*");
}
});
Events::on('on_note_undo_reblog', function ($reblogNote) {
if ($episodeId = $reblogNote->reblog_of_note->episode_id) {
$note = $reblogNote->reblog_of_note;
if ($episodeId = $note->episode_id) {
model('EpisodeModel')
->where('id', $episodeId)
->decrement('reblogs_total');
......@@ -121,6 +136,29 @@ Events::on('on_note_undo_reblog', function ($reblogNote) {
->where('id', $episodeId)
->decrement('notes_total');
}
cache()->deleteMatching("page_podcast#{$note->actor->podcast->id}*");
cache()->deleteMatching("page_note#{$note->id}*");
if ($reblogNote->actor->is_podcast) {
cache()->deleteMatching(
"page_podcast#{$reblogNote->actor->podcast->id}*",
);
}
});
Events::on('on_note_reply', function ($reply) {
$note = $reply->reply_to_note;
cache()->deleteMatching("page_podcast#{$note->actor->podcast->id}*");
cache()->deleteMatching("page_note#{$note->id}*");
});
Events::on('on_reply_remove', function ($reply) {
$note = $reply->reply_to_note;
cache()->deleteMatching("page_podcast#{$note->actor->podcast->id}*");
cache()->deleteMatching("page_note#{$note->id}*");
});
Events::on('on_note_favourite', function ($actor, $note) {
......@@ -129,6 +167,13 @@ Events::on('on_note_favourite', function ($actor, $note) {
->where('id', $note->episode_id)
->increment('favourites_total');
}
cache()->deleteMatching("page_podcast#{$actor->podcast->id}*");
cache()->deleteMatching("page_note#{$note->id}*");
if ($note->in_reply_to_id) {
cache()->deleteMatching("page_note#{$note->in_reply_to_id}*");
}
});
Events::on('on_note_undo_favourite', function ($actor, $note) {
......@@ -137,4 +182,31 @@ Events::on('on_note_undo_favourite', function ($actor, $note) {
->where('id', $note->episode_id)
->decrement('favourites_total');
}
cache()->deleteMatching("page_podcast#{$actor->podcast->id}*");
cache()->deleteMatching("page_note#{$note->id}*");
if ($note->in_reply_to_id) {
cache()->deleteMatching("page_note#{$note->in_reply_to_id}*");
}
});
Events::on('on_block_actor', function ($actorId) {
cache()->deleteMatching('page_podcast*');
cache()->deleteMatching('page_note*');
});
Events::on('on_unblock_actor', function ($actorId) {
cache()->deleteMatching('page_podcast*');
cache()->deleteMatching('page_note*');
});
Events::on('on_block_domain', function ($domainName) {
cache()->deleteMatching('page_podcast*');
cache()->deleteMatching('page_note*');
});
Events::on('on_unblock_domain', function ($domainName) {
cache()->deleteMatching('page_podcast*');
cache()->deleteMatching('page_note*');
});
......@@ -651,7 +651,7 @@ $routes->group('@(:podcastName)', function ($routes) {
// Other pages
$routes->get('/credits', 'Page::credits', ['as' => 'credits']);
$routes->get('/(:slug)', 'Page/$1', ['as' => 'page']);
$routes->get('/pages/(:slug)', 'Page/$1', ['as' => 'page']);
// interacting as an actor
$routes->post('interact-as-actor', 'Auth::attemptInteractAsActor', [
......
......@@ -8,15 +8,32 @@
namespace App\Controllers;
use Analytics\AnalyticsTrait;
class Actor extends \ActivityPub\Controllers\ActorController
{
use AnalyticsTrait;
public function follow()
{
helper(['form', 'components', 'svg']);
$data = [
'actor' => $this->actor,
];
// Prevent analytics hit when authenticated
if (!can_user_interact()) {
$this->registerPodcastWebpageHit($this->actor->podcast->id);
}
$cacheName = "page_podcast@{$this->actor->username}_follow";
if (!($cachedView = cache($cacheName))) {
helper(['form', 'components', 'svg']);
$data = [
'actor' => $this->actor,
];
return view('podcast/follow', $data, [
'cache' => DECADE,
'cache_name' => $cacheName,
]);
}
return view('podcast/follow', $data);
return $cachedView;
}
}