mirror of
https://github.com/openvk/openvk
synced 2025-03-14 21:45:22 +03:00
Merge branch 'master' into feature-reports
This commit is contained in:
commit
1b469c6e60
102 changed files with 1022 additions and 598 deletions
|
@ -38,6 +38,7 @@
|
|||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/console" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-php80" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/service-contracts" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/wapmorgan/morphos" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
<path value="$PROJECT_DIR$/vendor/symfony/console" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php80" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/service-contracts" />
|
||||
<path value="$PROJECT_DIR$/vendor/wapmorgan/morphos" />
|
||||
</include_path>
|
||||
</component>
|
||||
<component name="PhpProjectSharedConfiguration" php_language_level="7.4">
|
||||
|
|
28
README.md
28
README.md
|
@ -12,13 +12,15 @@ To be honest, we don't know whether it even works. However, this version is main
|
|||
|
||||
We will release OpenVK as soon as it's ready. As for now you can:
|
||||
* `git clone` this repo's master branch (use `git pull` to update)
|
||||
* Grab a prebuilt OpenVK distro from [GitHub artifacts](https://github.com/openvk/archive/actions/workflows/nightly.yml)
|
||||
* Grab a prebuilt OpenVK distro from [GitHub artifacts](https://nightly.link/openvk/archive/workflows/nightly/master/OpenVK%20Archive.zip)
|
||||
|
||||
## Instances
|
||||
|
||||
* **[openvk.su](https://openvk.su/)**
|
||||
* **[openvk.uk](https://openvk.uk)** - official mirror of openvk.su (<https://t.me/openvkch/1609>)
|
||||
* **[openvk.co](http://openvk.co)** - yet another official mirror of openvk.su without TLS (<https://t.me/openvkch/1654>)
|
||||
* [social.fetbuk.ru](http://social.fetbuk.ru/)
|
||||
* [vepurovk.xyz](http://vepurovk.xyz/)
|
||||
|
||||
## Can I create my own OpenVK instance?
|
||||
|
||||
|
@ -34,27 +36,33 @@ If you want, you can add your instance to the list above so that people can regi
|
|||
|
||||
* PHP 8 has **not** yet been tested, so you should not expect it to work. (edit: it does not work).
|
||||
|
||||
2. Install [commitcaptcha](https://github.com/openvk/commitcaptcha) and OpenVK as Chandler extensions like this:
|
||||
2. Install MySQL-compatible database.
|
||||
|
||||
* We recommend using Percona Server, but any MySQL-compatible server should work
|
||||
* Server should be compatible with at least MySQL 5.6, MySQL 8.0+ recommended.
|
||||
* Support for MySQL 4.1+ is WIP, replace `utf8mb4` and `utf8mb4_unicode_520_ci` with `utf8` and `utf8_unicode_ci` in SQLs.
|
||||
|
||||
3. Install [commitcaptcha](https://github.com/openvk/commitcaptcha) and OpenVK as Chandler extensions like this:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/openvk/openvk /path/to/chandler/extensions/available/openvk
|
||||
git clone https://github.com/openvk/commitcaptcha /path/to/chandler/extensions/available/commitcaptcha
|
||||
```
|
||||
|
||||
3. And enable them:
|
||||
4. And enable them:
|
||||
|
||||
```bash
|
||||
ln -s /path/to/chandler/extensions/available/commitcaptcha /path/to/chandler/extensions/enabled/
|
||||
ln -s /path/to/chandler/extensions/available/openvk /path/to/chandler/extensions/enabled/
|
||||
```
|
||||
|
||||
4. Import `install/init-static-db.sql` to the **same database** you installed Chandler to and import all sqls from `install/sqls` to the **same database**
|
||||
5. Import `install/init-event-db.sql` to a **separate database** (Yandex.Clickhouse can also be used, higly recommended)
|
||||
6. Copy `openvk-example.yml` to `openvk.yml` and change options to your liking
|
||||
7. Run `composer install` in OpenVK directory
|
||||
8. Run `composer install` in commitcaptcha directory
|
||||
9. Move to `Web/static/js` and execute `yarn install`
|
||||
10. Set `openvk` as your root app in `chandler.yml`
|
||||
5. Import `install/init-static-db.sql` to the **same database** you installed Chandler to and import all sqls from `install/sqls` to the **same database**
|
||||
6. Import `install/init-event-db.sql` to a **separate database** (Yandex.Clickhouse can also be used, highly recommended)
|
||||
7. Copy `openvk-example.yml` to `openvk.yml` and change options to your liking
|
||||
8. Run `composer install` in OpenVK directory
|
||||
9. Run `composer install` in commitcaptcha directory
|
||||
10. Move to `Web/static/js` and execute `yarn install`
|
||||
11. Set `openvk` as your root app in `chandler.yml`
|
||||
|
||||
Once you are done, you can login as a system administrator on the network itself (no registration required):
|
||||
|
||||
|
|
40
README_RU.md
40
README_RU.md
|
@ -2,23 +2,25 @@
|
|||
|
||||
_[English](README.md)_
|
||||
|
||||
**OpenVK** это попытка создать простую CMS, которая ~~косплеит~~ имитирует старый ВКонтакте. Представленный здесь код пока не стабилен.
|
||||
**OpenVK** - это попытка создать простую CMS, которая ~~косплеит~~ имитирует старый ВКонтакте. На данный момент представленный здесь исходный код проекта пока не является стабильным.
|
||||
|
||||
ВКонтакте принадлежит Павлу Дурову и VK Group.
|
||||
|
||||
Честно говоря, мы даже не знаем, работает ли она вообще. Однако, эта версия поддерживается, и мы будем рады принять ваши сообщения об ошибках [в нашем баг-трекере](https://github.com/openvk/openvk/projects/1). Вы также можете отправлять их через [вкладку "Помощь"](https://openvk.su/support?act=new) (для этого вам понадобится учетная запись OVK).
|
||||
|
||||
## Когда релиз?
|
||||
## Когда выйдет релизная версия?
|
||||
|
||||
Мы выпустим OpenVK, как только он будет готов. На данный момент Вы можете:
|
||||
* Сделать `git clone` master ветки этой репозитории (используйте `git pull` для обновления)
|
||||
* Взять готовую сборку OpenVK из [GitHub Actions](https://github.com/openvk/archive/actions/workflows/nightly.yml)
|
||||
* Склонировать master ветку репозитория командой `git clone` (используйте `git pull` для обновления)
|
||||
* Взять готовую сборку OpenVK из [GitHub Actions](https://nightly.link/openvk/archive/workflows/nightly/master/OpenVK%20Archive.zip)
|
||||
|
||||
## Инстанции
|
||||
|
||||
* **[openvk.su](https://openvk.su/)**
|
||||
* **[openvk.uk](https://openvk.uk)** - официальное зеркало openvk.su (<https://t.me/openvkch/1609>)
|
||||
* **[openvk.co](http://openvk.co)** - ещё одно официальное зеркало openvk.su без TLS (<https://t.me/openvkch/1654>)
|
||||
* [social.fetbuk.ru](http://social.fetbuk.ru/)
|
||||
* [vepurovk.xyz](http://vepurovk.xyz/)
|
||||
|
||||
## Могу ли я создать свою собственную инстанцию OpenVK?
|
||||
|
||||
|
@ -32,35 +34,41 @@ _[English](README.md)_
|
|||
|
||||
1. Установите PHP 7.4, веб-сервер, Composer, Node.js, Yarn и [Chandler](https://github.com/openvk/chandler)
|
||||
|
||||
* PHP 8 еще **не** тестировался, поэтому не стоит ожидать, что он будет работать (обновление: он не работает).
|
||||
* PHP 8 еще **не** тестировался, поэтому не стоит ожидать, что он будет работать (UPD: он не работает).
|
||||
|
||||
2. Установите [commitcaptcha](https://github.com/openvk/commitcaptcha) и OpenVK в качестве расширений Chandler следующим образом:
|
||||
2. Установите MySQL-совместимую базу данных.
|
||||
|
||||
* Мы рекомендуем использовать Persona Server, но любая MySQL-совместимая база данных должна работать
|
||||
* Сервер должен поддерживать хотя бы MySQL 5.6, рекомендуется использовать MySQL 8.0+.
|
||||
* Поддержка для MySQL 4.1+ находится в процессе, а пока замените `utf8mb4` и `utf8mb4_unicode_520_ci` на `utf8` и `utf8_unicode_ci` в SQL-файлах, соответственно.
|
||||
|
||||
3. Установите [commitcaptcha](https://github.com/openvk/commitcaptcha) и OpenVK в качестве расширений Chandler:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/openvk/openvk /path/to/chandler/extensions/available/openvk
|
||||
git clone https://github.com/openvk/commitcaptcha /path/to/chandler/extensions/available/commitcaptcha
|
||||
```
|
||||
|
||||
3. И включите их:
|
||||
4. И включите их:
|
||||
|
||||
```bash
|
||||
ln -s /path/to/chandler/extensions/available/commitcaptcha /path/to/chandler/extensions/enabled/
|
||||
ln -s /path/to/chandler/extensions/available/openvk /path/to/chandler/extensions/enabled/
|
||||
```
|
||||
|
||||
4. Импортируйте `install/init-static-db.sql` в **ту же базу данных**, в которую вы установили Chandler, и импортируйте все SQL файлы из папки `install/sqls` в **ту же базу данных**
|
||||
5. Импортируйте `install/init-event-db.sql` в **отдельную базу данных** (Яндекс.Clickhouse также может быть использован, настоятельно рекомендуется)
|
||||
6. Скопируйте `openvk-example.yml` в `openvk.yml` и измените параметры
|
||||
7. Запустите `composer install` в директории OpenVK
|
||||
8. Запустите `composer install` в директории commitcaptcha
|
||||
9. Перейдите в `Web/static/js` и выполните `yarn install`
|
||||
10. Установите `openvk` в качестве корневого приложения в файле `chandler.yml`
|
||||
5. Импортируйте `install/init-static-db.sql` в **ту же базу данных**, в которую вы установили Chandler, и импортируйте все SQL файлы из папки `install/sqls` в **ту же базу данных**
|
||||
6. Импортируйте `install/init-event-db.sql` в **отдельную базу данных** (Яндекс.Clickhouse также может быть использован, настоятельно рекомендуется)
|
||||
7. Скопируйте `openvk-example.yml` в `openvk.yml` и измените параметры под свои нужды
|
||||
8. Запустите `composer install` в директории OpenVK
|
||||
9. Запустите `composer install` в директории commitcaptcha
|
||||
10. Перейдите в `Web/static/js` и выполните `yarn install`
|
||||
11. Установите `openvk` в качестве корневого приложения в файле `chandler.yml`
|
||||
|
||||
После этого вы можете войти как системный администратор в саму сеть (регистрация не требуется):
|
||||
|
||||
* **Логин**: `admin@localhost.localdomain6`
|
||||
* **Пароль**: `admin`
|
||||
* Перед использованием встроенной учетной записи рекомендуется сменить пароль.
|
||||
* Перед использованием встроенной учетной записи рекомендуется сменить пароль или отключить её.
|
||||
|
||||
💡Запутались? Полное руководство по установке доступно [здесь](https://docs.openvk.su/openvk_engine/centos8_installation/) (CentOS 8 [и](https://almalinux.org/ru/) [семейство](https://yum.oracle.com/oracle-linux-isos.html)).
|
||||
|
||||
|
@ -82,5 +90,5 @@ ln -s /path/to/chandler/extensions/available/openvk /path/to/chandler/extensions
|
|||
**Внимание**: баг-трекер, форум, телеграм- и matrix-чат являются публичными местами, и жалобы в OVK обслуживается волонтерами. Если вам нужно сообщить о чем-то, что не должно быть раскрыто широкой публике (например, сообщение об уязвимости), пожалуйста, свяжитесь с нами напрямую по этому адресу: **openvk [собака] tutanota [точка] com**.
|
||||
|
||||
<a href="https://codeberg.org/OpenVK/openvk">
|
||||
<img alt="Получить на Codeberg" src="https://codeberg.org/Codeberg/GetItOnCodeberg/media/branch/main/get-it-on-blue-on-white.png" height="60">
|
||||
<img alt="Get it on Codeberg" src="https://codeberg.org/Codeberg/GetItOnCodeberg/media/branch/main/get-it-on-blue-on-white.png" height="60">
|
||||
</a>
|
||||
|
|
|
@ -62,8 +62,26 @@ final class Users extends VKAPIRequestHandler
|
|||
$response[$i]->photo_max_orig = $usr->getAvatarURL();
|
||||
break;
|
||||
case 'photo_max':
|
||||
$response[$i]->photo_max = $usr->getAvatarURL();
|
||||
$response[$i]->photo_max = $usr->getAvatarURL("original");
|
||||
break;
|
||||
case 'photo_50':
|
||||
$response[$i]->photo_50 = $usr->getAvatarURL();
|
||||
break;
|
||||
case 'photo_100':
|
||||
$response[$i]->photo_50 = $usr->getAvatarURL("tiny");
|
||||
break;
|
||||
case 'photo_200':
|
||||
$response[$i]->photo_50 = $usr->getAvatarURL("normal");
|
||||
break;
|
||||
case 'photo_200_orig': // вообще не ебу к чему эта строка ну пусть будет кек
|
||||
$response[$i]->photo_50 = $usr->getAvatarURL("normal");
|
||||
break;
|
||||
case 'photo_400_orig':
|
||||
$response[$i]->photo_50 = $usr->getAvatarURL("normal");
|
||||
break;
|
||||
|
||||
// Она хочет быть выебанной видя матан
|
||||
// Покайфу когда ты Виет а вокруг лишь дискриминант
|
||||
case 'status':
|
||||
if($usr->getStatus() != null)
|
||||
$response[$i]->status = $usr->getStatus();
|
||||
|
|
|
@ -35,11 +35,42 @@ final class Wall extends VKAPIRequestHandler
|
|||
"date" => $attachment->getPublicationTime()->timestamp(),
|
||||
"id" => $attachment->getVirtualId(),
|
||||
"owner_id" => $attachment->getOwner()->getId(),
|
||||
"sizes" => array([
|
||||
"height" => 500, // Для временного компросима оставляю статическое число. Если каждый раз обращаться к файлу за количеством пикселов, то наступает пuпuська полная с производительностью, так что пока так
|
||||
"url" => $attachment->getURL(),
|
||||
"sizes" => array(
|
||||
[
|
||||
"height" => 2560,
|
||||
"url" => $attachment->getURLBySizeId("normal"),
|
||||
"type" => "m",
|
||||
"width" => 500,
|
||||
"width" => 2560,
|
||||
],
|
||||
[
|
||||
"height" => 130,
|
||||
"url" => $attachment->getURLBySizeId("tiny"),
|
||||
"type" => "o",
|
||||
"width" => 130,
|
||||
],
|
||||
[
|
||||
"height" => 604,
|
||||
"url" => $attachment->getURLBySizeId("normal"),
|
||||
"type" => "p",
|
||||
"width" => 604,
|
||||
],
|
||||
[
|
||||
"height" => 807,
|
||||
"url" => $attachment->getURLBySizeId("large"),
|
||||
"type" => "q",
|
||||
"width" => 807,
|
||||
],
|
||||
[
|
||||
"height" => 1280,
|
||||
"url" => $attachment->getURLBySizeId("larger"),
|
||||
"type" => "r",
|
||||
"width" => 1280,
|
||||
],
|
||||
[
|
||||
"height" => 75, // Для временного компросима оставляю статическое число. Если каждый раз обращаться к файлу за количеством пикселов, то наступает пuпuська полная с производительностью, так что пока так
|
||||
"url" => $attachment->getURLBySizeId("miniscule"),
|
||||
"type" => "s",
|
||||
"width" => 75,
|
||||
]),
|
||||
"text" => "",
|
||||
"has_tags" => false
|
||||
|
@ -168,11 +199,42 @@ final class Wall extends VKAPIRequestHandler
|
|||
"date" => $attachment->getPublicationTime()->timestamp(),
|
||||
"id" => $attachment->getVirtualId(),
|
||||
"owner_id" => $attachment->getOwner()->getId(),
|
||||
"sizes" => array([
|
||||
"height" => 500, // я ещё я заебался вставлять одинаковый код в два разных места
|
||||
"url" => $attachment->getURL(),
|
||||
"sizes" => array(
|
||||
[
|
||||
"height" => 2560,
|
||||
"url" => $attachment->getURLBySizeId("normal"),
|
||||
"type" => "m",
|
||||
"width" => 500,
|
||||
"width" => 2560,
|
||||
],
|
||||
[
|
||||
"height" => 130,
|
||||
"url" => $attachment->getURLBySizeId("tiny"),
|
||||
"type" => "o",
|
||||
"width" => 130,
|
||||
],
|
||||
[
|
||||
"height" => 604,
|
||||
"url" => $attachment->getURLBySizeId("normal"),
|
||||
"type" => "p",
|
||||
"width" => 604,
|
||||
],
|
||||
[
|
||||
"height" => 807,
|
||||
"url" => $attachment->getURLBySizeId("large"),
|
||||
"type" => "q",
|
||||
"width" => 807,
|
||||
],
|
||||
[
|
||||
"height" => 1280,
|
||||
"url" => $attachment->getURLBySizeId("larger"),
|
||||
"type" => "r",
|
||||
"width" => 1280,
|
||||
],
|
||||
[
|
||||
"height" => 75, // Для временного компросима оставляю статическое число. Если каждый раз обращаться к файлу за количеством пикселов, то наступает пuпuська полная с производительностью, так что пока так
|
||||
"url" => $attachment->getURLBySizeId("miniscule"),
|
||||
"type" => "s",
|
||||
"width" => 75,
|
||||
]),
|
||||
"text" => "",
|
||||
"has_tags" => false
|
||||
|
|
16
Vagrantfile
vendored
16
Vagrantfile
vendored
|
@ -1,16 +1,22 @@
|
|||
# -*- mode: ruby -*-
|
||||
# vi: set ft=ruby :
|
||||
Vagrant.configure("2") do |config|
|
||||
config.vm.box = "freebsd/FreeBSD-12.1-STABLE"
|
||||
config.vm.box = "freebsd/FreeBSD-13.1-RC2"
|
||||
config.vm.box_version = "2022.04.07"
|
||||
|
||||
config.vm.network "forwarded_port", guest: 80, host: 4000
|
||||
|
||||
config.vm.synced_folder ".", "/.ovk_release"
|
||||
|
||||
config.vm.provider "virtualbox" do |vb|
|
||||
vb.gui = true
|
||||
vb.memory = "1024"
|
||||
vb.cpus = 4
|
||||
vb.memory = "1568"
|
||||
end
|
||||
|
||||
config.vm.provider "vmware_workstation" do |vwx|
|
||||
vwx.gui = true
|
||||
vwx.vmx["memsize"] = "1568"
|
||||
vwx.vmx["numvcpus"] = "4"
|
||||
end
|
||||
|
||||
config.vm.provision "shell", inline: "/bin/tcsh /.ovk_release/install/automated/freebsd-12/install"
|
||||
config.vm.provision "shell", inline: "/bin/tcsh /.ovk_release/install/automated/freebsd-13/install"
|
||||
end
|
||||
|
|
|
@ -346,6 +346,11 @@ class Club extends RowModel
|
|||
{
|
||||
return $this->getRecord()->website;
|
||||
}
|
||||
|
||||
function getAlert(): ?string
|
||||
{
|
||||
return $this->getRecord()->alert;
|
||||
}
|
||||
|
||||
use Traits\TSubscribable;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,9 @@ abstract class Media extends Postable
|
|||
{
|
||||
protected $fileExtension = "oct"; #octet stream xddd
|
||||
protected $upperNodeReferenceColumnName = "owner";
|
||||
|
||||
protected $processingPlaceholder = NULL;
|
||||
protected $processingTime = 30;
|
||||
|
||||
function __destruct()
|
||||
{
|
||||
#Remove data, if model wasn't presisted
|
||||
|
@ -22,6 +24,11 @@ abstract class Media extends Postable
|
|||
else
|
||||
return OPENVK_ROOT . "/storage/";
|
||||
}
|
||||
|
||||
protected function checkIfFileIsProcessed(): bool
|
||||
{
|
||||
throw new \LogicException("checkIfFileIsProcessed is not implemented");
|
||||
}
|
||||
|
||||
abstract protected function saveFile(string $filename, string $hash): bool;
|
||||
|
||||
|
@ -41,6 +48,10 @@ abstract class Media extends Postable
|
|||
|
||||
function getURL(): string
|
||||
{
|
||||
if(!is_null($this->processingPlaceholder))
|
||||
if(!$this->isProcessed())
|
||||
return "/assets/packages/static/openvk/$this->processingPlaceholder.$this->fileExtension";
|
||||
|
||||
$hash = $this->getRecord()->hash;
|
||||
|
||||
switch(OPENVK_ROOT_CONF["openvk"]["preferences"]["uploads"]["mode"]) {
|
||||
|
@ -55,7 +66,7 @@ abstract class Media extends Postable
|
|||
case "server":
|
||||
$settings = (object) OPENVK_ROOT_CONF["openvk"]["preferences"]["uploads"]["server"];
|
||||
return (
|
||||
$settings->protocol .
|
||||
$settings->protocol ?? ovk_scheme() .
|
||||
"://" . $settings->host .
|
||||
$settings->path .
|
||||
substr($hash, 0, 2) . "/$hash.$this->fileExtension"
|
||||
|
@ -68,6 +79,26 @@ abstract class Media extends Postable
|
|||
{
|
||||
return $this->getRecord()->description;
|
||||
}
|
||||
|
||||
protected function isProcessed(): bool
|
||||
{
|
||||
if(is_null($this->processingPlaceholder))
|
||||
return true;
|
||||
|
||||
if($this->getRecord()->processed)
|
||||
return true;
|
||||
|
||||
$timeDiff = time() - $this->getRecord()->last_checked;
|
||||
if($timeDiff < $this->processingTime)
|
||||
return false;
|
||||
|
||||
$res = $this->checkIfFileIsProcessed();
|
||||
$this->stateChanges("last_checked", time());
|
||||
$this->stateChanges("processed", $res);
|
||||
$this->save();
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
function isDeleted(): bool
|
||||
{
|
||||
|
@ -89,7 +120,17 @@ abstract class Media extends Postable
|
|||
|
||||
$this->stateChanges("hash", $hash);
|
||||
}
|
||||
|
||||
|
||||
function save(): void
|
||||
{
|
||||
if(!is_null($this->processingPlaceholder) && is_null($this->getRecord())) {
|
||||
$this->stateChanges("processed", 0);
|
||||
$this->stateChanges("last_checked", time());
|
||||
}
|
||||
|
||||
parent::save();
|
||||
}
|
||||
|
||||
function delete(bool $softly = true): void
|
||||
{
|
||||
$deleteQuirk = ovkGetQuirk("blobs.erase-upon-deletion");
|
||||
|
|
|
@ -55,16 +55,21 @@ trait TRichText
|
|||
{
|
||||
$contentColumn = property_exists($this, "overrideContentColumn") ? $this->overrideContentColumn : "content";
|
||||
|
||||
$text = htmlentities($this->getRecord()->{$contentColumn}, ENT_DISALLOWED | ENT_XHTML);
|
||||
$text = htmlspecialchars($this->getRecord()->{$contentColumn}, ENT_DISALLOWED | ENT_XHTML);
|
||||
$proc = iconv_strlen($this->getRecord()->{$contentColumn}) <= OPENVK_ROOT_CONF["openvk"]["preferences"]["wall"]["postSizes"]["processingLimit"];
|
||||
if($html) {
|
||||
if($proc) {
|
||||
$rel = $this->isAd() ? "sponsored" : "ugc";
|
||||
$text = $this->formatLinks($text);
|
||||
$text = preg_replace("%@([A-Za-z0-9]++) \(([\p{L} 0-9]+)\)%Xu", "[$1|$2]", $text);
|
||||
$text = preg_replace("%@([A-Za-z0-9]++) \(((?:[\p{L&}\p{Lo} 0-9]\p{Mn}?)++)\)%Xu", "[$1|$2]", $text);
|
||||
$text = preg_replace("%([\n\r\s]|^)(@([A-Za-z0-9]++))%Xu", "$1[$3|@$3]", $text);
|
||||
$text = preg_replace("%\[([A-Za-z0-9]++)\|([\p{L} 0-9@]+)\]%Xu", "<a href='/$1'>$2</a>", $text);
|
||||
$text = preg_replace("%([\n\r\s]|^)(#([\p{L}_-]++[0-9]*[\p{L}_-]*))%Xu", "$1<a href='/feed/hashtag/$3'>$2</a>", $text);
|
||||
$text = preg_replace("%\[([A-Za-z0-9]++)\|((?:[\p{L&}\p{Lo} 0-9@]\p{Mn}?)++)\]%Xu", "<a href='/$1'>$2</a>", $text);
|
||||
$text = preg_replace_callback("%([\n\r\s]|^)(\#([\p{L}_0-9][\p{L}_0-9\(\)\-\']+[\p{L}_0-9\(\)]|[\p{L}_0-9]{1,2}))%Xu", function($m) {
|
||||
$slug = rawurlencode($m[3]);
|
||||
|
||||
return "$m[1]<a href='/feed/hashtag/$slug'>$m[2]</a>";
|
||||
}, $text);
|
||||
|
||||
$text = $this->formatEmojis($text);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<?php declare(strict_types=1);
|
||||
namespace openvk\Web\Models\Entities;
|
||||
use morphos\Gender;
|
||||
use openvk\Web\Themes\{Themepack, Themepacks};
|
||||
use openvk\Web\Util\DateTime;
|
||||
use openvk\Web\Models\RowModel;
|
||||
|
@ -9,6 +10,7 @@ use openvk\Web\Models\Exceptions\InvalidUserNameException;
|
|||
use Nette\Database\Table\ActiveRow;
|
||||
use Chandler\Database\DatabaseConnection;
|
||||
use Chandler\Security\User as ChandlerUser;
|
||||
use function morphos\Russian\inflectName;
|
||||
|
||||
class User extends RowModel
|
||||
{
|
||||
|
@ -166,50 +168,61 @@ class User extends RowModel
|
|||
|
||||
return $this->getFirstName() . $pseudo . $this->getLastName();
|
||||
}
|
||||
|
||||
function getMorphedName(string $case = "genitive", bool $fullName = true): string
|
||||
{
|
||||
$name = $fullName ? ($this->getLastName() . " " . $this->getFirstName()) : $this->getFirstName();
|
||||
if(!preg_match("%^[А-яё\-]+$%", $name))
|
||||
return $name; # name is probably not russian
|
||||
|
||||
$inflected = inflectName($name, $case, $this->isFemale() ? Gender::FEMALE : Gender::MALE);
|
||||
|
||||
return $inflected ?: $name;
|
||||
}
|
||||
|
||||
function getCanonicalName(): string
|
||||
{
|
||||
if($this->getRecord()->deleted)
|
||||
if($this->getRecord()->deleted)
|
||||
return "DELETED";
|
||||
else
|
||||
return $this->getFirstName() . ' ' . $this->getLastName();
|
||||
else
|
||||
return $this->getFirstName() . " " . $this->getLastName();
|
||||
}
|
||||
|
||||
|
||||
function getPhone(): ?string
|
||||
{
|
||||
return $this->getRecord()->phone;
|
||||
}
|
||||
|
||||
|
||||
function getEmail(): ?string
|
||||
{
|
||||
return $this->getRecord()->email;
|
||||
}
|
||||
|
||||
|
||||
function getOnline(): DateTime
|
||||
{
|
||||
return new DateTime($this->getRecord()->online);
|
||||
}
|
||||
|
||||
|
||||
function getDescription(): ?string
|
||||
{
|
||||
return $this->getRecord()->about;
|
||||
}
|
||||
|
||||
|
||||
function getStatus(): ?string
|
||||
{
|
||||
return $this->getRecord()->status;
|
||||
}
|
||||
|
||||
|
||||
function getShortCode(): ?string
|
||||
{
|
||||
return $this->getRecord()->shortcode;
|
||||
}
|
||||
|
||||
|
||||
function getAlert(): ?string
|
||||
{
|
||||
return $this->getRecord()->alert;
|
||||
}
|
||||
|
||||
|
||||
function getBanReason(): ?string
|
||||
{
|
||||
return $this->getRecord()->block_reason;
|
||||
|
@ -219,105 +232,105 @@ class User extends RowModel
|
|||
{
|
||||
return $this->getRecord()->block_in_support_reason;
|
||||
}
|
||||
|
||||
|
||||
function getType(): int
|
||||
{
|
||||
return $this->getRecord()->type;
|
||||
}
|
||||
|
||||
|
||||
function getCoins(): float
|
||||
{
|
||||
if(!OPENVK_ROOT_CONF["openvk"]["preferences"]["commerce"])
|
||||
return 0.0;
|
||||
|
||||
|
||||
return $this->getRecord()->coins;
|
||||
}
|
||||
|
||||
|
||||
function getRating(): int
|
||||
{
|
||||
return OPENVK_ROOT_CONF["openvk"]["preferences"]["commerce"] ? $this->getRecord()->rating : 0;
|
||||
}
|
||||
|
||||
|
||||
function getReputation(): int
|
||||
{
|
||||
return $this->getRecord()->reputation;
|
||||
}
|
||||
|
||||
|
||||
function getRegistrationTime(): DateTime
|
||||
{
|
||||
return new DateTime($this->getRecord()->since->getTimestamp());
|
||||
}
|
||||
|
||||
|
||||
function getRegistrationIP(): string
|
||||
{
|
||||
return $this->getRecord()->registering_ip;
|
||||
}
|
||||
|
||||
|
||||
function getHometown(): ?string
|
||||
{
|
||||
return $this->getRecord()->hometown;
|
||||
}
|
||||
|
||||
|
||||
function getPoliticalViews(): int
|
||||
{
|
||||
return $this->getRecord()->polit_views;
|
||||
}
|
||||
|
||||
|
||||
function getMaritalStatus(): int
|
||||
{
|
||||
return $this->getRecord()->marital_status;
|
||||
}
|
||||
|
||||
|
||||
function getContactEmail(): ?string
|
||||
{
|
||||
return $this->getRecord()->email_contact;
|
||||
}
|
||||
|
||||
|
||||
function getTelegram(): ?string
|
||||
{
|
||||
return $this->getRecord()->telegram;
|
||||
}
|
||||
|
||||
|
||||
function getInterests(): ?string
|
||||
{
|
||||
return $this->getRecord()->interests;
|
||||
}
|
||||
|
||||
|
||||
function getFavoriteMusic(): ?string
|
||||
{
|
||||
return $this->getRecord()->fav_music;
|
||||
}
|
||||
|
||||
|
||||
function getFavoriteFilms(): ?string
|
||||
{
|
||||
return $this->getRecord()->fav_films;
|
||||
}
|
||||
|
||||
|
||||
function getFavoriteShows(): ?string
|
||||
{
|
||||
return $this->getRecord()->fav_shows;
|
||||
}
|
||||
|
||||
|
||||
function getFavoriteBooks(): ?string
|
||||
{
|
||||
return $this->getRecord()->fav_books;
|
||||
}
|
||||
|
||||
|
||||
function getFavoriteQuote(): ?string
|
||||
{
|
||||
return $this->getRecord()->fav_quote;
|
||||
}
|
||||
|
||||
|
||||
function getCity(): ?string
|
||||
{
|
||||
return $this->getRecord()->city;
|
||||
}
|
||||
|
||||
|
||||
function getPhysicalAddress(): ?string
|
||||
{
|
||||
return $this->getRecord()->address;
|
||||
}
|
||||
|
||||
|
||||
function getNotificationOffset(): int
|
||||
{
|
||||
return $this->getRecord()->notification_offset;
|
||||
|
@ -332,7 +345,7 @@ class User extends RowModel
|
|||
{
|
||||
return (int)floor((time() - $this->getBirthday()->timestamp()) / YEAR);
|
||||
}
|
||||
|
||||
|
||||
function get2faSecret(): ?string
|
||||
{
|
||||
return $this->getRecord()["2fa_secret"];
|
||||
|
@ -347,7 +360,7 @@ class User extends RowModel
|
|||
{
|
||||
$this->stateChanges("notification_offset", time());
|
||||
}
|
||||
|
||||
|
||||
function getLeftMenuItemStatus(string $id): bool
|
||||
{
|
||||
return (bool) bmask($this->getRecord()->left_menu, [
|
||||
|
@ -364,7 +377,7 @@ class User extends RowModel
|
|||
],
|
||||
])->get($id);
|
||||
}
|
||||
|
||||
|
||||
function getPrivacySetting(string $id): int
|
||||
{
|
||||
return (int) bmask($this->getRecord()->privacy, [
|
||||
|
@ -383,7 +396,7 @@ class User extends RowModel
|
|||
],
|
||||
])->get($id);
|
||||
}
|
||||
|
||||
|
||||
function getPrivacyPermission(string $permission, ?User $user = NULL): bool
|
||||
{
|
||||
$permStatus = $this->getPrivacySetting($permission);
|
||||
|
@ -391,7 +404,7 @@ class User extends RowModel
|
|||
return $permStatus === User::PRIVACY_EVERYONE;
|
||||
else if($user->getId() === $this->getId())
|
||||
return true;
|
||||
|
||||
|
||||
switch($permStatus) {
|
||||
case User::PRIVACY_ONLY_FRIENDS:
|
||||
return $this->getSubscriptionStatus($user) === User::SUBSCRIPTION_MUTUAL;
|
||||
|
@ -402,12 +415,12 @@ class User extends RowModel
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function getProfileCompletenessReport(): object
|
||||
{
|
||||
$incompleteness = 0;
|
||||
$unfilled = [];
|
||||
|
||||
|
||||
if(!$this->getRecord()->status) {
|
||||
$unfilled[] = "status";
|
||||
$incompleteness += 15;
|
||||
|
@ -428,46 +441,46 @@ class User extends RowModel
|
|||
$unfilled[] = "interests";
|
||||
$incompleteness += 20;
|
||||
}
|
||||
|
||||
|
||||
$total = max(100 - $incompleteness + $this->getRating(), 0);
|
||||
if(ovkGetQuirk("profile.rating-bar-behaviour") === 0)
|
||||
if ($total >= 100)
|
||||
$percent = round(($total / 10**strlen(strval($total))) * 100, 0);
|
||||
else
|
||||
$percent = min($total, 100);
|
||||
|
||||
|
||||
return (object) [
|
||||
"total" => $total,
|
||||
"percent" => $percent,
|
||||
"unfilled" => $unfilled,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
function getFriends(int $page = 1, int $limit = 6): \Traversable
|
||||
{
|
||||
return $this->_abstractRelationGenerator("get-friends", $page, $limit);
|
||||
}
|
||||
|
||||
|
||||
function getFriendsCount(): int
|
||||
{
|
||||
return $this->_abstractRelationCount("get-friends");
|
||||
}
|
||||
|
||||
|
||||
function getFollowers(int $page = 1, int $limit = 6): \Traversable
|
||||
{
|
||||
return $this->_abstractRelationGenerator("get-followers", $page, $limit);
|
||||
}
|
||||
|
||||
|
||||
function getFollowersCount(): int
|
||||
{
|
||||
return $this->_abstractRelationCount("get-followers");
|
||||
}
|
||||
|
||||
|
||||
function getSubscriptions(int $page = 1, int $limit = 6): \Traversable
|
||||
{
|
||||
return $this->_abstractRelationGenerator("get-subscriptions-user", $page, $limit);
|
||||
}
|
||||
|
||||
|
||||
function getSubscriptionsCount(): int
|
||||
{
|
||||
return $this->_abstractRelationCount("get-subscriptions-user");
|
||||
|
@ -477,7 +490,7 @@ class User extends RowModel
|
|||
{
|
||||
return sizeof(DatabaseConnection::i()->getContext()->table("messages")->where(["recipient_id" => $this->getId(), "unread" => 1]));
|
||||
}
|
||||
|
||||
|
||||
function getClubs(int $page = 1, bool $admin = false): \Traversable
|
||||
{
|
||||
if($admin) {
|
||||
|
@ -502,7 +515,7 @@ class User extends RowModel
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function getClubCount(bool $admin = false): int
|
||||
{
|
||||
if($admin) {
|
||||
|
@ -517,7 +530,7 @@ class User extends RowModel
|
|||
return sizeof($sel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function getPinnedClubs(): \Traversable
|
||||
{
|
||||
foreach($this->getRecord()->related("groups.owner")->where("owner_club_pinned", true) as $target) {
|
||||
|
@ -558,16 +571,16 @@ class User extends RowModel
|
|||
foreach($sel as $target) {
|
||||
$target = (new Clubs)->get($target->event);
|
||||
if(!$target) continue;
|
||||
|
||||
|
||||
yield $target;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function getMeetingCount(): int
|
||||
{
|
||||
return sizeof($this->getRecord()->related("event_turnouts.user"));
|
||||
}
|
||||
|
||||
|
||||
function getGifts(int $page = 1, ?int $perPage = NULL): \Traversable
|
||||
{
|
||||
$gifts = $this->getRecord()->related("gift_user_relations.receiver")->order("sent DESC")->page($page, $perPage ?? OPENVK_DEFAULT_PER_PAGE);
|
||||
|
@ -581,7 +594,7 @@ class User extends RowModel
|
|||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function getGiftCount(): int
|
||||
{
|
||||
return sizeof($this->getRecord()->related("gift_user_relations.receiver"));
|
||||
|
@ -616,9 +629,9 @@ class User extends RowModel
|
|||
|
||||
function use2faBackupCode(int $code): bool
|
||||
{
|
||||
return (bool) $this->getRecord()->related("2fa_backup_codes.owner")->where("code", $code)->delete();
|
||||
return (bool) $this->getRecord()->related("2fa_backup_codes.owner")->where("code", $code)->delete();
|
||||
}
|
||||
|
||||
|
||||
function getSubscriptionStatus(User $user): int
|
||||
{
|
||||
$subbed = !is_null($this->getRecord()->related("subscriptions.follower")->where([
|
||||
|
@ -629,51 +642,51 @@ class User extends RowModel
|
|||
"model" => static::class,
|
||||
"follower" => $user->getId(),
|
||||
])->fetch());
|
||||
|
||||
|
||||
if($subbed && $followed) return User::SUBSCRIPTION_MUTUAL;
|
||||
if($subbed) return User::SUBSCRIPTION_INCOMING;
|
||||
if($followed) return User::SUBSCRIPTION_OUTGOING;
|
||||
|
||||
|
||||
return User::SUBSCRIPTION_ABSENT;
|
||||
}
|
||||
|
||||
|
||||
function getNotificationsCount(bool $archived = false): int
|
||||
{
|
||||
return (new Notifications)->getNotificationCountByUser($this, $this->getNotificationOffset(), $archived);
|
||||
}
|
||||
|
||||
|
||||
function getNotifications(int $page, bool $archived = false): \Traversable
|
||||
{
|
||||
return (new Notifications)->getNotificationsByUser($this, $this->getNotificationOffset(), $archived, $page);
|
||||
}
|
||||
|
||||
|
||||
function getPendingPhoneVerification(): ?ActiveRow
|
||||
{
|
||||
return $this->getRecord()->ref("number_verification", "id");
|
||||
}
|
||||
|
||||
|
||||
function getRefLinkId(): string
|
||||
{
|
||||
$hash = hash_hmac("Snefru", (string) $this->getId(), CHANDLER_ROOT_CONF["security"]["secret"], true);
|
||||
|
||||
|
||||
return dechex($this->getId()) . " " . base64_encode($hash);
|
||||
}
|
||||
|
||||
|
||||
function getNsfwTolerance(): int
|
||||
{
|
||||
return $this->getRecord()->nsfw_tolerance;
|
||||
}
|
||||
|
||||
|
||||
function isFemale(): bool
|
||||
{
|
||||
return (bool) $this->getRecord()->sex;
|
||||
}
|
||||
|
||||
|
||||
function isVerified(): bool
|
||||
{
|
||||
return (bool) $this->getRecord()->verified;
|
||||
}
|
||||
|
||||
|
||||
function isBanned(): bool
|
||||
{
|
||||
return !is_null($this->getBanReason());
|
||||
|
@ -683,22 +696,22 @@ class User extends RowModel
|
|||
{
|
||||
return !is_null($this->getBanInSupportReason());
|
||||
}
|
||||
|
||||
|
||||
function isOnline(): bool
|
||||
{
|
||||
return time() - $this->getRecord()->online <= 300;
|
||||
}
|
||||
|
||||
|
||||
function prefersNotToSeeRating(): bool
|
||||
{
|
||||
return !((bool) $this->getRecord()->show_rating);
|
||||
}
|
||||
|
||||
|
||||
function hasPendingNumberChange(): bool
|
||||
{
|
||||
return !is_null($this->getPendingPhoneVerification());
|
||||
}
|
||||
|
||||
|
||||
function gift(User $sender, Gift $gift, ?string $comment = NULL, bool $anonymous = false): void
|
||||
{
|
||||
DatabaseConnection::i()->getContext()->table("gift_user_relations")->insert([
|
||||
|
@ -710,7 +723,7 @@ class User extends RowModel
|
|||
"sent" => time(),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
function ban(string $reason, bool $deleteSubscriptions = true): void
|
||||
{
|
||||
if($deleteSubscriptions) {
|
||||
|
@ -723,42 +736,42 @@ class User extends RowModel
|
|||
);
|
||||
$subs->delete();
|
||||
}
|
||||
|
||||
|
||||
$this->setBlock_Reason($reason);
|
||||
$this->save();
|
||||
}
|
||||
|
||||
|
||||
function verifyNumber(string $code): bool
|
||||
{
|
||||
$ver = $this->getPendingPhoneVerification();
|
||||
if(!$ver) return false;
|
||||
|
||||
|
||||
try {
|
||||
if(sodium_memcmp((string) $ver->code, $code) === -1) return false;
|
||||
} catch(\SodiumException $ex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$this->setPhone($ver->number);
|
||||
$this->save();
|
||||
|
||||
|
||||
DatabaseConnection::i()->getContext()
|
||||
->table("number_verification")
|
||||
->where("user", $this->getId())
|
||||
->delete();
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function setFirst_Name(string $firstName): void
|
||||
{
|
||||
$firstName = mb_convert_case($firstName, MB_CASE_TITLE);
|
||||
if(!preg_match('%^[\p{Lu}\p{Lo}]\p{Mn}?(?:[\p{L&}\p{Lo}]\p{Mn}?){1,16}$%u', $firstName))
|
||||
throw new InvalidUserNameException;
|
||||
|
||||
|
||||
$this->stateChanges("first_name", $firstName);
|
||||
}
|
||||
|
||||
|
||||
function setLast_Name(string $lastName): void
|
||||
{
|
||||
if(!empty($lastName))
|
||||
|
@ -767,15 +780,15 @@ class User extends RowModel
|
|||
if(!preg_match('%^[\p{Lu}\p{Lo}]\p{Mn}?([\p{L&}\p{Lo}]\p{Mn}?){1,16}(\-\g<1>+)?$%u', $lastName))
|
||||
throw new InvalidUserNameException;
|
||||
}
|
||||
|
||||
|
||||
$this->stateChanges("last_name", $lastName);
|
||||
}
|
||||
|
||||
|
||||
function setNsfwTolerance(int $tolerance): void
|
||||
{
|
||||
$this->stateChanges("nsfw_tolerance", $tolerance);
|
||||
}
|
||||
|
||||
|
||||
function setPrivacySetting(string $id, int $status): void
|
||||
{
|
||||
$this->stateChanges("privacy", bmask($this->changes["privacy"] ?? $this->getRecord()->privacy, [
|
||||
|
@ -794,7 +807,7 @@ class User extends RowModel
|
|||
],
|
||||
])->set($id, $status)->toInteger());
|
||||
}
|
||||
|
||||
|
||||
function setLeftMenuItemStatus(string $id, bool $status): void
|
||||
{
|
||||
$mask = bmask($this->changes["left_menu"] ?? $this->getRecord()->left_menu, [
|
||||
|
@ -810,10 +823,10 @@ class User extends RowModel
|
|||
"poster",
|
||||
],
|
||||
])->set($id, (int) $status)->toInteger();
|
||||
|
||||
|
||||
$this->stateChanges("left_menu", $mask);
|
||||
}
|
||||
|
||||
|
||||
function setShortCode(?string $code = NULL, bool $force = false): ?bool
|
||||
{
|
||||
if(!is_null($code)) {
|
||||
|
@ -825,20 +838,20 @@ class User extends RowModel
|
|||
return false;
|
||||
if(\Chandler\MVC\Routing\Router::i()->getMatchingRoute("/$code")[0]->presenter !== "UnknownTextRouteStrategy")
|
||||
return false;
|
||||
|
||||
|
||||
$pClub = DatabaseConnection::i()->getContext()->table("groups")->where("shortcode", $code)->fetch();
|
||||
if(!is_null($pClub))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$this->stateChanges("shortcode", $code);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function setPhoneWithVerification(string $phone): string
|
||||
{
|
||||
$code = unpack("S", openssl_random_pseudo_bytes(2))[1];
|
||||
|
||||
|
||||
if($this->hasPendingNumberChange()) {
|
||||
DatabaseConnection::i()->getContext()
|
||||
->table("number_verification")
|
||||
|
@ -849,10 +862,10 @@ class User extends RowModel
|
|||
->table("number_verification")
|
||||
->insert(["user" => $this->getId(), "number" => $phone, "code" => $code]);
|
||||
}
|
||||
|
||||
|
||||
return (string) $code;
|
||||
}
|
||||
|
||||
|
||||
# KABOBSQL temporary fix
|
||||
# Tuesday, the 7th of January 2020 @ 22:43 <Menhera>: implementing quick fix to this problem and monitoring
|
||||
# NOTICE: this is an ongoing conversation, add your comments just above this line. Thanks!
|
||||
|
@ -860,10 +873,10 @@ class User extends RowModel
|
|||
{
|
||||
$this->stateChanges("shortcode", $this->getRecord()->shortcode); #fix KABOBSQL
|
||||
$this->stateChanges("online", $time);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function adminNotify(string $message): bool
|
||||
{
|
||||
$admId = OPENVK_ROOT_CONF["openvk"]["preferences"]["support"]["adminAccount"];
|
||||
|
@ -871,12 +884,12 @@ class User extends RowModel
|
|||
return false;
|
||||
else if(is_null($admin = (new Users)->get($admId)))
|
||||
return false;
|
||||
|
||||
|
||||
$cor = new Correspondence($admin, $this);
|
||||
$msg = new Message;
|
||||
$msg->setContent($message);
|
||||
$cor->sendMessage($msg, true);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -903,7 +916,7 @@ class User extends RowModel
|
|||
case 2:
|
||||
return 2;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
|
|
|
@ -14,6 +14,8 @@ class Video extends Media
|
|||
|
||||
protected $tableName = "videos";
|
||||
protected $fileExtension = "ogv";
|
||||
|
||||
protected $processingPlaceholder = "video/rendering";
|
||||
|
||||
protected function saveFile(string $filename, string $hash): bool
|
||||
{
|
||||
|
@ -37,7 +39,7 @@ class Video extends Media
|
|||
throw new \DomainException("$filename does not contain any meaningful video streams");
|
||||
|
||||
try {
|
||||
if(!is_dir($dirId = $this->pathFromHash($hash)))
|
||||
if(!is_dir($dirId = dirname($this->pathFromHash($hash))))
|
||||
mkdir($dirId);
|
||||
|
||||
$dir = $this->getBaseDir();
|
||||
|
@ -53,7 +55,23 @@ class Video extends Media
|
|||
usleep(200100);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
protected function checkIfFileIsProcessed(): bool
|
||||
{
|
||||
if($this->getType() != Video::TYPE_DIRECT)
|
||||
return true;
|
||||
|
||||
if(!file_exists($this->getFileName())) {
|
||||
if((time() - $this->getRecord()->last_checked) > 3600) {
|
||||
// TODO notify that video processor is probably dead
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function getName(): string
|
||||
{
|
||||
return $this->getRecord()->name;
|
||||
|
@ -83,6 +101,9 @@ class Video extends Media
|
|||
function getThumbnailURL(): string
|
||||
{
|
||||
if($this->getType() === Video::TYPE_DIRECT) {
|
||||
if(!$this->isProcessed())
|
||||
return "/assets/packages/static/openvk/video/rendering.apng";
|
||||
|
||||
return preg_replace("%\.[A-z]++$%", ".gif", $this->getURL());
|
||||
} else {
|
||||
return $this->getVideoDriver()->getThumbnailURL();
|
||||
|
|
|
@ -45,7 +45,7 @@ class Clubs
|
|||
|
||||
function getPopularClubs(): \Traversable
|
||||
{
|
||||
$query = "SELECT ROW_NUMBER() OVER (ORDER BY `subscriptions` DESC) as `place`, `target` as `id`, COUNT(`follower`) as `subscriptions` FROM `subscriptions` WHERE `model` = \"openvk\\\Web\\\Models\\\Entities\\\Club\" GROUP BY `target` ORDER BY `subscriptions` DESC, `id` LIMIT 10;";
|
||||
$query = "SELECT ROW_NUMBER() OVER (ORDER BY `subscriptions` DESC) as `place`, `target` as `id`, COUNT(`follower`) as `subscriptions` FROM `subscriptions` WHERE `model` = \"openvk\\\Web\\\Models\\\Entities\\\Club\" GROUP BY `target` ORDER BY `subscriptions` DESC, `id` LIMIT 30;";
|
||||
$entries = DatabaseConnection::i()->getConnection()->query($query);
|
||||
|
||||
foreach($entries as $entry)
|
||||
|
|
|
@ -13,7 +13,7 @@ Move-Item $file $temp
|
|||
|
||||
# video stub logic was implicitly deprecated, so we start processing at once
|
||||
ffmpeg -i $temp -ss 00:00:01.000 -vframes 1 "$dir$hashT/$hash.gif"
|
||||
ffmpeg -i $temp -c:v libtheora -q:v 7 -c:a libvorbis -q:a 4 -vf scale=640x360,setsar=1:1 -y $temp2
|
||||
ffmpeg -i $temp -c:v libtheora -q:v 7 -c:a libvorbis -q:a 4 -vf "scale=640:480:force_original_aspect_ratio=decrease,pad=640:480:(ow-iw)/2:(oh-ih)/2,setsar=1" -y $temp2
|
||||
|
||||
Move-Item $temp2 "$dir$hashT/$hash.ogv"
|
||||
Remove-Item $temp
|
||||
|
|
|
@ -5,7 +5,7 @@ cp ../files/video/rendering.apng $3${4:0:2}/$4.gif
|
|||
cp ../files/video/rendering.ogv $3/${4:0:2}/$4.ogv
|
||||
|
||||
nice ffmpeg -i "/tmp/vid_$tmpfile.bin" -ss 00:00:01.000 -vframes 1 $3${4:0:2}/$4.gif
|
||||
nice -n 20 ffmpeg -i "/tmp/vid_$tmpfile.bin" -c:v libtheora -q:v 7 -c:a libvorbis -q:a 4 -vf scale=640x360,setsar=1:1 -y "/tmp/ffmOi$tmpfile.ogv"
|
||||
nice -n 20 ffmpeg -i "/tmp/vid_$tmpfile.bin" -c:v libtheora -q:v 7 -c:a libvorbis -q:a 4 -vf "scale=640:480:force_original_aspect_ratio=decrease,pad=640:480:(ow-iw)/2:(oh-ih)/2,setsar=1" -y "/tmp/ffmOi$tmpfile.ogv"
|
||||
|
||||
rm -rf $3${4:0:2}/$4.ogv
|
||||
mv "/tmp/ffmOi$tmpfile.ogv" $3${4:0:2}/$4.ogv
|
||||
|
|
|
@ -126,4 +126,11 @@ final class AboutPresenter extends OpenVKPresenter
|
|||
header("Location: https://github.com/openvk/openvk#readme");
|
||||
exit;
|
||||
}
|
||||
|
||||
function renderDev(): void
|
||||
{
|
||||
header("HTTP/1.1 302 Found");
|
||||
header("Location: https://docs.openvk.su/");
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,20 +17,23 @@ final class BlobPresenter extends OpenVKPresenter
|
|||
function renderFile(/*string*/ $dir, string $name, string $format)
|
||||
{
|
||||
$dir = $this->getDirName($dir);
|
||||
$name = preg_replace("%[^a-zA-Z0-9_\-]++%", "", $name);
|
||||
$path = OPENVK_ROOT . "/storage/$dir/$name.$format";
|
||||
if(!file_exists($path)) {
|
||||
$base = realpath(OPENVK_ROOT . "/storage/$dir");
|
||||
$path = realpath(OPENVK_ROOT . "/storage/$dir/$name.$format");
|
||||
if(!$path) # Will also check if file exists since realpath fails on ENOENT
|
||||
$this->notFound();
|
||||
} else {
|
||||
if(isset($_SERVER["HTTP_IF_NONE_MATCH"]))
|
||||
else if(strpos($path, $path) !== 0) # Prevent directory traversal and storage container escape
|
||||
$this->notFound();
|
||||
|
||||
if(isset($_SERVER["HTTP_IF_NONE_MATCH"]))
|
||||
exit(header("HTTP/1.1 304 Not Modified"));
|
||||
|
||||
header("Content-Type: " . mime_content_type($path));
|
||||
header("Content-Size: " . filesize($path));
|
||||
header("Cache-Control: public, max-age=1210000");
|
||||
header("X-Accel-Expires: 1210000");
|
||||
header("ETag: W/\"" . hash_file("snefru", $path) . "\"");
|
||||
|
||||
readfile($path);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,6 +72,8 @@ final class PhotosPresenter extends OpenVKPresenter
|
|||
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
if(empty($this->postParam("name")))
|
||||
$this->flashFail("err", tr("error"), tr("error_segmentation"));
|
||||
else if(strlen($this->postParam("name")) > 36)
|
||||
$this->flashFail("err", tr("error"), tr("error_data_too_big", "name", 36, "bytes"));
|
||||
|
||||
$album = new Album;
|
||||
$album->setOwner(isset($club) ? $club->getId() * -1 : $this->user->id);
|
||||
|
@ -100,6 +102,9 @@ final class PhotosPresenter extends OpenVKPresenter
|
|||
$this->template->album = $album;
|
||||
|
||||
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
if(strlen($this->postParam("name")) > 36)
|
||||
$this->flashFail("err", tr("error"), tr("error_data_too_big", "name", 36, "bytes"));
|
||||
|
||||
$album->setName(empty($this->postParam("name")) ? $album->getName() : $this->postParam("name"));
|
||||
$album->setDescription(empty($this->postParam("desc")) ? NULL : $this->postParam("desc"));
|
||||
$album->setEdited(time());
|
||||
|
|
|
@ -481,6 +481,22 @@ final class UserPresenter extends OpenVKPresenter
|
|||
$this->flashFail("succ", tr("information_-1"), tr("two_factor_authentication_disabled_message"));
|
||||
}
|
||||
|
||||
function renderResetThemepack(): void
|
||||
{
|
||||
$this->assertNoCSRF();
|
||||
|
||||
$this->setSessionTheme(Themepacks::DEFAULT_THEME_ID);
|
||||
|
||||
if($this->user) {
|
||||
$this->willExecuteWriteAction();
|
||||
|
||||
$this->user->identity->setStyle(Themepacks::DEFAULT_THEME_ID);
|
||||
$this->user->identity->save();
|
||||
}
|
||||
|
||||
$this->redirect("/", static::REDIRECT_TEMPORARY_PRESISTENT);
|
||||
}
|
||||
|
||||
function renderCoinsTransfer(): void
|
||||
{
|
||||
$this->assertUserLoggedIn();
|
||||
|
|
|
@ -303,8 +303,6 @@ final class WallPresenter extends OpenVKPresenter
|
|||
|
||||
function renderPost(int $wall, int $post_id): void
|
||||
{
|
||||
$this->assertUserLoggedIn();
|
||||
|
||||
$post = $this->posts->getPostById($wall, $post_id);
|
||||
if(!$post || $post->isDeleted())
|
||||
$this->notFound();
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
</div>
|
||||
|
||||
<div class="container_gray">
|
||||
{var data = is_array($iterator) ? $iterator : iterator_to_array($iterator)}
|
||||
{var $data = is_array($iterator) ? $iterator : iterator_to_array($iterator)}
|
||||
|
||||
{if sizeof($data) > 0}
|
||||
<div class="content" n:foreach="$data as $dat">
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
{block wrap}
|
||||
<div class="ovk-lw-container">
|
||||
<div class="ovk-lw--list">
|
||||
{var data = is_array($iterator) ? $iterator : iterator_to_array($iterator)}
|
||||
{var $data = is_array($iterator) ? $iterator : iterator_to_array($iterator)}
|
||||
|
||||
{if sizeof($data) > 0}
|
||||
<table n:foreach="$data as $dat" border="0" style="font-size:11px;" class="post">
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
{var instance_name = OPENVK_ROOT_CONF['openvk']['appearance']['name']}
|
||||
|
||||
{var $instance_name = OPENVK_ROOT_CONF['openvk']['appearance']['name']}
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{var instance_name = OPENVK_ROOT_CONF['openvk']['appearance']['name']}
|
||||
|
||||
{var $instance_name = OPENVK_ROOT_CONF['openvk']['appearance']['name']}
|
||||
{if !isset($parentModule) || substr($parentModule, 0, 21) === 'libchandler:absolute.'}
|
||||
<!DOCTYPE html>
|
||||
<html n:if="!isset($parentModule) || substr($parentModule, 0, 21) === 'libchandler:absolute.'">
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
{ifset title}{include title} - {/ifset}{$instance_name}
|
||||
|
@ -169,9 +169,9 @@
|
|||
</a>
|
||||
<a href="/settings" class="link">{_my_settings}</a>
|
||||
|
||||
{var canAccessAdminPanel = $thisUser->getChandlerUser()->can("access")->model("admin")->whichBelongsTo(NULL)}
|
||||
{var canAccessHelpdesk = $thisUser->getChandlerUser()->can("write")->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)}
|
||||
{var menuLinksAvaiable = sizeof(OPENVK_ROOT_CONF['openvk']['preferences']['menu']['links']) > 0 && $thisUser->getLeftMenuItemStatus('links')}
|
||||
{var $canAccessAdminPanel = $thisUser->getChandlerUser()->can("access")->model("admin")->whichBelongsTo(NULL)}
|
||||
{var $canAccessHelpdesk = $thisUser->getChandlerUser()->can("write")->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)}
|
||||
{var $menuLinksAvaiable = sizeof(OPENVK_ROOT_CONF['openvk']['preferences']['menu']['links']) > 0 && $thisUser->getLeftMenuItemStatus('links')}
|
||||
<div n:if="$canAccessAdminPanel || $canAccessHelpdesk || $menuLinksAvaiable" class="menu_divider"></div>
|
||||
<a href="/admin" class="link" n:if="$canAccessAdminPanel" title="Админ-панель [Alt+Shift+A]" accesskey="a">Админ-панель</a>
|
||||
<a href="/support/tickets" class="link" n:if="$canAccessHelpdesk">Helpdesk
|
||||
|
@ -191,6 +191,14 @@
|
|||
<div n:if="$thisUser->getPinnedClubCount() > 0" class="menu_divider"></div>
|
||||
<a n:foreach="$thisUser->getPinnedClubs() as $club" href="{$club->getURL()}" class="link group_link">{$club->getName()}</a>
|
||||
</div>
|
||||
|
||||
<div n:if="OPENVK_ROOT_CONF['openvk']['preferences']['commerce'] && $thisUser->getCoins() != 0" id="votesBalance">
|
||||
{tr("you_still_have_x_points", $thisUser->getCoins())|noescape}
|
||||
<br /><br />
|
||||
|
||||
<a href="/settings?act=finance">{_top_up_your_account} »</a>
|
||||
</div>
|
||||
|
||||
<a n:if="OPENVK_ROOT_CONF['openvk']['preferences']['adPoster']['enable'] && $thisUser->getLeftMenuItemStatus('poster')" href="{php echo OPENVK_ROOT_CONF['openvk']['preferences']['adPoster']['link']}" >
|
||||
<img src="{php echo OPENVK_ROOT_CONF['openvk']['preferences']['adPoster']['src']}" alt="{php echo OPENVK_ROOT_CONF['openvk']['preferences']['adPoster']['caption']}" class="psa-poster" style="max-width: 100%; margin-top: 50px;" />
|
||||
</a>
|
||||
|
@ -256,7 +264,7 @@
|
|||
</div>
|
||||
|
||||
<div class="page_footer">
|
||||
{var dbVersion = \Chandler\Database\DatabaseConnection::i()->getConnection()->getPdo()->getAttribute(\PDO::ATTR_SERVER_VERSION)}
|
||||
{var $dbVersion = \Chandler\Database\DatabaseConnection::i()->getConnection()->getPdo()->getAttribute(\PDO::ATTR_SERVER_VERSION)}
|
||||
|
||||
<div class="navigation_footer">
|
||||
<a href="/about" class="link">{_footer_about_instance}</a>
|
||||
|
@ -330,6 +338,7 @@
|
|||
{/ifset}
|
||||
</body>
|
||||
</html>
|
||||
{/if}
|
||||
|
||||
{if isset($parentModule) && substr($parentModule, 0, 21) !== 'libchandler:absolute.'}
|
||||
<!-- INCLUDING TEMPLATE FROM PARENTMODULE: {$parentModule} -->
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
{include specpage, x => $dat}
|
||||
{else}
|
||||
<div class="container_gray">
|
||||
{var data = is_array($iterator) ? $iterator : iterator_to_array($iterator)}
|
||||
{var $data = is_array($iterator) ? $iterator : iterator_to_array($iterator)}
|
||||
|
||||
{if sizeof($data) > 0}
|
||||
<div class="content" n:foreach="$data as $dat">
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<table width="100%" cellspacing="0" cellpadding="0">
|
||||
<tbody>
|
||||
<tr valign="top">
|
||||
<td width="250" {if sizeof($admins) > 0}style="padding-right: 10px;"{/if}>
|
||||
<td width="250"{if sizeof($admins) > 0} style="padding-right: 10px;"{/if}>
|
||||
<h4>{_statistics}</h4>
|
||||
<div style="margin-top: 5px;">
|
||||
{_on_this_instance_are}
|
||||
|
@ -21,6 +21,15 @@
|
|||
<li><span>{tr("about_wall_posts", $postsCount)|noescape}</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
{if OPENVK_ROOT_CONF['openvk']['preferences']['about']['links']}
|
||||
<h4>{_about_links}</h4>
|
||||
<div style="margin-top: 5px;">
|
||||
{_instance_links}
|
||||
<ul>
|
||||
<li n:foreach="OPENVK_ROOT_CONF['openvk']['preferences']['about']['links'] as $aboutLink"><a href="{$aboutLink['url']}" target="_blank" class="link">{$aboutLink["name"]}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
{/if}
|
||||
</td>
|
||||
<td n:if="sizeof($admins) > 0">
|
||||
<h4>{_administrators}</h4>
|
||||
|
@ -44,14 +53,23 @@
|
|||
|
||||
{if sizeof($popularClubs) !== 0}
|
||||
<h4>{_most_popular_groups}</h4>
|
||||
<ol>
|
||||
<li n:foreach="$popularClubs as $entry" style="margin-top: 5px;">
|
||||
<a href="{$entry->club->getURL()}">{$entry->club->getName()}</a>
|
||||
<div>
|
||||
{tr("participants", $entry->subscriptions)}
|
||||
</div>
|
||||
</li>
|
||||
</ol>
|
||||
{var $entries = array_chunk($popularClubs, 10, true)}
|
||||
<table width="100%" cellspacing="0" cellpadding="0">
|
||||
<tbody>
|
||||
<tr valign="top">
|
||||
<td n:foreach="$entries as $chunk">
|
||||
<ol>
|
||||
<li value="{$num+1}" style="margin-top: 5px;" n:foreach="$chunk as $num => $club">
|
||||
<a href="{$club->club->getURL()}">{$club->club->getName()}</a>
|
||||
<div>
|
||||
{tr("participants", $club->subscriptions)}
|
||||
</div>
|
||||
</li>
|
||||
</ol>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{/if}
|
||||
|
||||
<h4>{_rules}</h4>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<head>
|
||||
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8" />
|
||||
<style>
|
||||
{var css = file_get_contents(OPENVK_ROOT . "/Web/static/js/node_modules/@atlassian/aui/dist/aui/aui-prototyping.css")}
|
||||
{var $css = file_get_contents(OPENVK_ROOT . "/Web/static/js/node_modules/@atlassian/aui/dist/aui/aui-prototyping.css")}
|
||||
{str_replace("fonts/", "/assets/packages/static/openvk/js/node_modules/@atlassian/aui/dist/aui/fonts/", $css)|noescape}
|
||||
</style>
|
||||
<title>{include title} - Админ-панель {=OPENVK_ROOT_CONF['openvk']['appearance']['name']}</title>
|
||||
|
@ -131,7 +131,7 @@
|
|||
</div>
|
||||
<section class="aui-page-panel-content">
|
||||
{ifset $flashMessage}
|
||||
{var type = ["err" => "error", "warn" => "warning", "info" => "basic", "succ" => "success"][$flashMessage->type]}
|
||||
{var $type = ["err" => "error", "warn" => "warning", "info" => "basic", "succ" => "success"][$flashMessage->type]}
|
||||
<div class="aui-message aui-message-{$type}" style="margin-bottom: 15px;">
|
||||
<p class="title">
|
||||
<strong>{$flashMessage->title}</strong>
|
||||
|
|
|
@ -11,9 +11,9 @@
|
|||
|
||||
{block content}
|
||||
|
||||
{var isMain = $mode === 'main'}
|
||||
{var isBan = $mode === 'ban'}
|
||||
{var isFollowers = $mode === 'followers'}
|
||||
{var $isMain = $mode === 'main'}
|
||||
{var $isBan = $mode === 'ban'}
|
||||
{var $isFollowers = $mode === 'followers'}
|
||||
|
||||
{if $isMain}
|
||||
|
||||
|
@ -134,7 +134,7 @@
|
|||
|
||||
<!-- This followers block -->
|
||||
|
||||
{var followers = iterator_to_array($followers)}
|
||||
{var $followers = iterator_to_array($followers)}
|
||||
|
||||
<div class="aui-tabs horizontal-tabs">
|
||||
<nav class="aui-navgroup aui-navgroup-horizontal">
|
||||
|
@ -177,7 +177,7 @@
|
|||
</tbody>
|
||||
</table>
|
||||
<div align="right">
|
||||
{var isLast = ((20 * (($_GET['p'] ?? 1) - 1)) + $amount) < $count}
|
||||
{var $isLast = ((20 * (($_GET['p'] ?? 1) - 1)) + $amount) < $count}
|
||||
|
||||
<a n:if="($_GET['p'] ?? 1) > 1" class="aui-button" href="?p={($_GET['p'] ?? 1) - 1}">
|
||||
⭁ туда
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{extends "@layout.xml"}
|
||||
{var search = true}
|
||||
{var $search = true}
|
||||
|
||||
{block title}
|
||||
Группы
|
||||
|
@ -12,8 +12,8 @@
|
|||
{block searchTitle}Поиск бутылок{/block}
|
||||
|
||||
{block content}
|
||||
{var clubs = iterator_to_array($clubs)}
|
||||
{var amount = sizeof($clubs)}
|
||||
{var $clubs = iterator_to_array($clubs)}
|
||||
{var $amount = sizeof($clubs)}
|
||||
|
||||
<table class="aui aui-table-list">
|
||||
<thead>
|
||||
|
@ -39,7 +39,7 @@
|
|||
<a href="{$club->getURL()}">{$club->getCanonicalName()}</a>
|
||||
</td>
|
||||
<td>
|
||||
{var user = $club->getOwner()}
|
||||
{var $user = $club->getOwner()}
|
||||
|
||||
<span class="aui-avatar aui-avatar-xsmall">
|
||||
<span class="aui-avatar-inner">
|
||||
|
@ -61,7 +61,7 @@
|
|||
</table>
|
||||
<br/>
|
||||
<div align="right">
|
||||
{var isLast = ((10 * (($_GET['p'] ?? 1) - 1)) + $amount) < $count}
|
||||
{var $isLast = ((10 * (($_GET['p'] ?? 1) - 1)) + $amount) < $count}
|
||||
|
||||
<a n:if="($_GET['p'] ?? 1) > 1" class="aui-button" href="?p={($_GET['p'] ?? 1) - 1}">
|
||||
⭁ туда
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
{/if}
|
||||
|
||||
<div align="right">
|
||||
{var isLast = ((20 * (($_GET['p'] ?? 1) - 1)) + sizeof($categories)) < $count}
|
||||
{var $isLast = ((20 * (($_GET['p'] ?? 1) - 1)) + sizeof($categories)) < $count}
|
||||
<a n:if="($_GET['p'] ?? 1) > 1" class="aui-button" href="?act={$act}&p={($_GET['p'] ?? 1) - 1}">
|
||||
⭁ туда
|
||||
</a>
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
{/if}
|
||||
|
||||
<div align="right">
|
||||
{var isLast = ((20 * (($_GET['p'] ?? 1) - 1)) + sizeof($gifts)) < $count}
|
||||
{var $isLast = ((20 * (($_GET['p'] ?? 1) - 1)) + sizeof($gifts)) < $count}
|
||||
<a n:if="($_GET['p'] ?? 1) > 1" class="aui-button" href="?p={($_GET['p'] ?? 1) - 1}">
|
||||
⭁ туда
|
||||
</a>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{extends "@layout.xml"}
|
||||
{var search = true}
|
||||
{var $search = true}
|
||||
|
||||
{block title}
|
||||
Пользователи
|
||||
|
@ -12,8 +12,8 @@
|
|||
{block searchTitle}Поиск пиздюков{/block}
|
||||
|
||||
{block content}
|
||||
{var users = iterator_to_array($users)}
|
||||
{var amount = sizeof($users)}
|
||||
{var $users = iterator_to_array($users)}
|
||||
{var $amount = sizeof($users)}
|
||||
|
||||
<table class="aui aui-table-list">
|
||||
<thead>
|
||||
|
@ -60,7 +60,7 @@
|
|||
</table>
|
||||
<br/>
|
||||
<div align="right">
|
||||
{var isLast = ((20 * (($_GET['p'] ?? 1) - 1)) + $amount) < $count}
|
||||
{var $isLast = ((20 * (($_GET['p'] ?? 1) - 1)) + $amount) < $count}
|
||||
|
||||
<a n:if="($_GET['p'] ?? 1) > 1" class="aui-button" href="?p={($_GET['p'] ?? 1) - 1}">
|
||||
⭁ туда
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
<br/>
|
||||
|
||||
<div align="right">
|
||||
{var isLast = ((20 * (($_GET['p'] ?? 1) - 1)) + sizeof($vouchers)) < $count}
|
||||
{var $isLast = ((20 * (($_GET['p'] ?? 1) - 1)) + sizeof($vouchers)) < $count}
|
||||
<a n:if="($_GET['p'] ?? 1) > 1" class="aui-button" href="?p={($_GET['p'] ?? 1) - 1}">
|
||||
⭁ туда
|
||||
</a>
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
<span>{_"gender"}: </span>
|
||||
</td>
|
||||
<td>
|
||||
{var femalePreferred = OPENVK_ROOT_CONF["openvk"]["preferences"]["femaleGenderPriority"]}
|
||||
{var $femalePreferred = OPENVK_ROOT_CONF["openvk"]["preferences"]["femaleGenderPriority"]}
|
||||
<select name="sex" required>
|
||||
<option n:attr="selected => !$femalePreferred" value="male">{_"male"}</option>
|
||||
<option n:attr="selected => $femalePreferred" value="female">{_"female"}</option>
|
||||
|
|
|
@ -92,7 +92,7 @@
|
|||
<span class="nobold">{_group_administrators_list}: </span>
|
||||
</td>
|
||||
<td>
|
||||
{var areAllAdminsHidden = $club->getManagersCount(true) == 0}
|
||||
{var $areAllAdminsHidden = $club->getManagersCount(true) == 0}
|
||||
<input type="radio" name="administrators_list_display" value="0" n:attr="checked => $club->getAdministratorsListDisplay() == 0, disabled => $areAllAdminsHidden" /> {_group_display_only_creator}<br>
|
||||
<input type="radio" name="administrators_list_display" value="1" n:attr="checked => $club->getAdministratorsListDisplay() == 1, disabled => $areAllAdminsHidden" /> {_group_display_all_administrators}<br>
|
||||
<input type="radio" name="administrators_list_display" value="2" n:attr="checked => $club->getAdministratorsListDisplay() == 2" /> {_group_dont_display_administrators_list}<br>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{extends "../@listView.xml"}
|
||||
{var $Manager = openvk\Web\Models\Entities\Manager::class}
|
||||
{var iterator = $onlyShowManagers ? $managers : $followers}
|
||||
{var count = $paginatorConf->count}
|
||||
{var page = $paginatorConf->page}
|
||||
{var perPage = 6}
|
||||
{var $iterator = $onlyShowManagers ? $managers : $followers}
|
||||
{var $count = $paginatorConf->count}
|
||||
{var $page = $paginatorConf->page}
|
||||
{var $perPage = 6}
|
||||
|
||||
{block title}{_followers} {$club->getCanonicalName()}{/block}
|
||||
|
||||
|
@ -49,8 +49,8 @@
|
|||
{/block}
|
||||
|
||||
{block description}
|
||||
{var user = $x instanceof $Manager ? $x->getUser() : $x}
|
||||
{var manager = $x instanceof $Manager ? $x : $club->getManager($user, !$club->canBeModifiedBy($thisUser))}
|
||||
{var $user = $x instanceof $Manager ? $x->getUser() : $x}
|
||||
{var $manager = $x instanceof $Manager ? $x : $club->getManager($user, !$club->canBeModifiedBy($thisUser))}
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
|
@ -106,8 +106,8 @@
|
|||
{/block}
|
||||
|
||||
{block actions}
|
||||
{var user = $x instanceof $Manager ? $x->getUser() : $x}
|
||||
{var manager = $x instanceof $Manager ? $x : $club->getManager($user, !$club->canBeModifiedBy($thisUser))}
|
||||
{var $user = $x instanceof $Manager ? $x->getUser() : $x}
|
||||
{var $manager = $x instanceof $Manager ? $x : $club->getManager($user, !$club->canBeModifiedBy($thisUser))}
|
||||
{if $club->canBeModifiedBy($thisUser ?? NULL)}
|
||||
<a class="profile_link" href="/club{$club->getId()}/setAdmin?user={$user->getId()}&hash={rawurlencode($csrfToken)}" n:if="$club->getOwner()->getId() !== $user->getId()">
|
||||
{if $manager}
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
{block content}
|
||||
<div class="left_big_block">
|
||||
<div n:if="!is_null($alert = $club->getAlert())" class="group-alert">{strpos($alert, "@") === 0 ? tr(substr($alert, 1)) : $alert}</div>
|
||||
|
||||
<div class="content_title_expanded" onclick="hidePanel(this);">
|
||||
{_"information"}
|
||||
</div>
|
||||
|
@ -41,7 +43,7 @@
|
|||
</table>
|
||||
</div>
|
||||
<div n:if="$club->getFollowersCount() > 0">
|
||||
{var followersCount = $club->getFollowersCount()}
|
||||
{var $followersCount = $club->getFollowersCount()}
|
||||
|
||||
<div class="content_title_expanded" onclick="hidePanel(this, {$followersCount});">
|
||||
{_participants}
|
||||
|
@ -91,8 +93,8 @@
|
|||
{presenter "openvk!Wall->wallEmbedded", -$club->getId()}
|
||||
</div>
|
||||
<div class="right_small_block">
|
||||
{var avatarPhoto = $club->getAvatarPhoto()}
|
||||
{var avatarLink = ((is_null($avatarPhoto) ? FALSE : $avatarPhoto->isAnonymous()) ? "/photo" . ("s/" . base_convert((string) $avatarPhoto->getId(), 10, 32)) : $club->getAvatarLink())}
|
||||
{var $avatarPhoto = $club->getAvatarPhoto()}
|
||||
{var $avatarLink = ((is_null($avatarPhoto) ? FALSE : $avatarPhoto->isAnonymous()) ? "/photo" . ("s/" . base_convert((string) $avatarPhoto->getId(), 10, 32)) : $club->getAvatarLink())}
|
||||
<a href="{$avatarLink|nocheck}">
|
||||
<img src="{$club->getAvatarUrl('normal')}" style="width: 100%; image-rendering: -webkit-optimize-contrast;" />
|
||||
</a>
|
||||
|
@ -132,7 +134,7 @@
|
|||
{_"creator"}
|
||||
</div>
|
||||
<div class="avatar-list-item" style="padding: 8px;">
|
||||
{var author = $club->getOwner()}
|
||||
{var $author = $club->getOwner()}
|
||||
<div class="avatar">
|
||||
<a href="{$author->getURL()}">
|
||||
<img class="ava" src="{$author->getAvatarUrl()}" />
|
||||
|
@ -149,7 +151,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div n:if="$club->getAdministratorsListDisplay() == 1">
|
||||
{var managersCount = $club->getManagersCount(true)}
|
||||
{var $managersCount = $club->getManagersCount(true)}
|
||||
|
||||
<div class="content_title_expanded" onclick="hidePanel(this, {$managersCount});">
|
||||
{_"administrators"}
|
||||
|
@ -163,7 +165,7 @@
|
|||
</div>
|
||||
<div class="avatar-list">
|
||||
<div class="avatar-list-item" n:if="!$club->isOwnerHidden()">
|
||||
{var author = $club->getOwner()}
|
||||
{var $author = $club->getOwner()}
|
||||
<div class="avatar">
|
||||
<a href="{$author->getURL()}">
|
||||
<img class="ava" src="{$author->getAvatarUrl()}" />
|
||||
|
@ -175,7 +177,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="avatar-list-item" n:foreach="$club->getManagers(1, true) as $manager">
|
||||
{var user = $manager->getUser()}
|
||||
{var $user = $manager->getUser()}
|
||||
<div class="avatar">
|
||||
<a href="{$user->getURL()}">
|
||||
<img height="32" class="ava" src="{$user->getAvatarUrl()}" />
|
||||
|
@ -203,7 +205,7 @@
|
|||
<div style="padding: 5px;">
|
||||
<div class="ovk-album" style="display: inline-block;" n:foreach="$albums as $album">
|
||||
<div style="text-align: center;float: left;height: 54pt;width: 100px;">
|
||||
{var cover = $album->getCoverPhoto()}
|
||||
{var $cover = $album->getCoverPhoto()}
|
||||
|
||||
<img
|
||||
src="{is_null($cover)?'/assets/packages/static/openvk/img/camera_200.png':$cover->getURL()}"
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<a href="/im">{_my_messages}</a> »
|
||||
<a href="{$correspondent->getURL()}">{$correspondent->getCanonicalName()}</a>
|
||||
<div n:if="($online = $correspondent->getOnline()->timestamp()) + 2505600 > time()" style="float: right;">
|
||||
{var diff = date_diff(date_create(), date_create('@' . $online))}
|
||||
{var $diff = date_diff(date_create(), date_create('@' . $online))}
|
||||
{if 5 >= $diff->i}
|
||||
<span><b>{_online}</b></span>
|
||||
{else}
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
<div n:foreach="$corresps as $coresp"
|
||||
class="crp-entry"
|
||||
onmousedown="window.location.href = {$coresp->getURL()};" >
|
||||
{var recipient = $coresp->getCorrespondents()[1]}
|
||||
{var lastMsg = $coresp->getPreviewMessage()}
|
||||
{var $recipient = $coresp->getCorrespondents()[1]}
|
||||
{var $lastMsg = $coresp->getPreviewMessage()}
|
||||
|
||||
<div class="crp-entry--image">
|
||||
<img src="{$recipient->getAvatarURL('miniscule')}"
|
||||
|
@ -33,7 +33,7 @@
|
|||
<span>{$lastMsg->getSendTime()->format("%e %B %G" . tr("time_at_sp") . "%X")}</span>
|
||||
</div>
|
||||
<div n:class="crp-entry--message, $lastMsg->getUnreadState() ? unread">
|
||||
{var _author = $lastMsg->getSender()}
|
||||
{var $_author = $lastMsg->getSender()}
|
||||
|
||||
<div class="crp-entry--message---av" n:if="$_author->getId() === $thisUser->getId()">
|
||||
<img src="{$_author->getAvatarURL('miniscule')}"
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
{block title}{_edit_note}{/block}
|
||||
|
||||
{block header}
|
||||
{var author = $note->getOwner()}
|
||||
{var $author = $note->getOwner()}
|
||||
<a href="{$author->getURL()}">{$author->getCanonicalName()}</a>
|
||||
»
|
||||
<a href="/notes{$author->getId()}">{_notes}</a>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{extends "../@listView.xml"}
|
||||
{var iterator = iterator_to_array($notes)}
|
||||
{var page = $paginatorConf->page}
|
||||
{var $iterator = iterator_to_array($notes)}
|
||||
{var $page = $paginatorConf->page}
|
||||
|
||||
{block title}{_notes}{/block}
|
||||
|
||||
|
@ -62,7 +62,7 @@
|
|||
|
||||
<div class="container_gray" style="background: white; border-top: none;">
|
||||
|
||||
{var data = is_array($iterator) ? $iterator : iterator_to_array($iterator)}
|
||||
{var $data = is_array($iterator) ? $iterator : iterator_to_array($iterator)}
|
||||
{if sizeof($data) > 0}
|
||||
|
||||
<div n:foreach="$data as $dat">
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
{block title}{$note->getName()}{/block}
|
||||
|
||||
{block header}
|
||||
{var author = $note->getOwner()}
|
||||
{var $author = $note->getOwner()}
|
||||
<a href="{$author->getURL()}">{$author->getCanonicalName()}</a>
|
||||
»
|
||||
<a href="/notes{$author->getId()}">{_notes}</a>
|
||||
|
@ -12,7 +12,7 @@
|
|||
{/block}
|
||||
|
||||
{block content}
|
||||
{var author = $note->getOwner()}
|
||||
{var $author = $note->getOwner()}
|
||||
<style>
|
||||
#userContent img {
|
||||
max-width: 245pt;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{extends "../@listView.xml"}
|
||||
{var sorting = false}
|
||||
{var $sorting = false}
|
||||
|
||||
{block title}
|
||||
{_feedback}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
{block title}Альбом {$album->getName()}{/block}
|
||||
|
||||
{block header}
|
||||
{var isClub = ($album->getOwner() instanceof openvk\Web\Models\Entities\Club)}
|
||||
{var $isClub = ($album->getOwner() instanceof openvk\Web\Models\Entities\Club)}
|
||||
|
||||
<a href="{$album->getOwner()->getURL()}">
|
||||
{$album->getOwner()->getCanonicalName()}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{extends "../@listView.xml"}
|
||||
{var iterator = iterator_to_array($albums)}
|
||||
{var page = $paginatorConf->page}
|
||||
{var $iterator = iterator_to_array($albums)}
|
||||
{var $page = $paginatorConf->page}
|
||||
|
||||
{block title}{_"albums"} {$owner->getCanonicalName()}{/block}
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
|||
|
||||
<span n:if="$canEdit" style="float: right;">
|
||||
|
|
||||
{var isClub = ($owner instanceof \openvk\Web\Models\Entities\Club)}
|
||||
{var $isClub = ($owner instanceof \openvk\Web\Models\Entities\Club)}
|
||||
<a href="/albums/create{$isClub ? '?gpid=' . $owner->getId() : ''}">{_create_album}</a>
|
||||
</span>
|
||||
</div>
|
||||
|
@ -44,8 +44,8 @@
|
|||
{/block}
|
||||
|
||||
{block preview}
|
||||
{var cover = $x->getCoverPhoto()}
|
||||
{var preview = is_null($cover) ? "/assets/packages/static/openvk/img/camera_200.png" : $cover->getURLBySizeId("normal")}
|
||||
{var $cover = $x->getCoverPhoto()}
|
||||
{var $preview = is_null($cover) ? "/assets/packages/static/openvk/img/camera_200.png" : $cover->getURLBySizeId("normal")}
|
||||
|
||||
<a href="/album{$x->getPrettyId()}">
|
||||
<img src="{$preview}" alt="{$x->getName()}" style="height: 130px; width: 170px; object-fit: cover" />
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
{if $thisUser->getChandlerUser()->can("write")->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)}
|
||||
<a href="{$comment->getUser()->getURL()}">
|
||||
<span class="nobold">
|
||||
{var lastName = $comment->getUser()->getLastName()}
|
||||
{var $lastName = $comment->getUser()->getLastName()}
|
||||
{if empty(trim($lastName))}
|
||||
({$comment->getUser()->getFirstName()})
|
||||
{else}
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
{/block}
|
||||
|
||||
{block content}
|
||||
{var isMain = $mode === 'faq'}
|
||||
{var isNew = $mode === 'new'}
|
||||
{var isList = $mode === 'list'}
|
||||
{var $isMain = $mode === 'faq'}
|
||||
{var $isNew = $mode === 'new'}
|
||||
{var $isList = $mode === 'list'}
|
||||
|
||||
{if $thisUser}
|
||||
<div class="tabs">
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
{/block}
|
||||
|
||||
{block description}
|
||||
{var author = $x->getUser()}
|
||||
{var $author = $x->getUser()}
|
||||
|
||||
{ovk_proc_strtr($x->getContext(), 50)}<br/>
|
||||
<span class="nobold">{_author}: </span> <a href="{$author->getURL()}">{$author->getCanonicalName()}</a>
|
||||
|
|
|
@ -109,7 +109,7 @@
|
|||
|
||||
{if $comment->getUType() === 1}
|
||||
<div class="post-menu">
|
||||
{var isLikedByUser = $comment->isLikedByUser()}
|
||||
{var $isLikedByUser = $comment->isLikedByUser()}
|
||||
<strong id="markText-{$comment->getId()}">
|
||||
{if !is_null($isLikedByUser)}
|
||||
{if $comment->isLikedByUser()}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{extends "../@listView.xml"}
|
||||
{var iterator = iterator_to_array($topics)}
|
||||
{var page = $paginatorConf->page}
|
||||
{var $iterator = iterator_to_array($topics)}
|
||||
{var $page = $paginatorConf->page}
|
||||
|
||||
{block title}{_discussions} {$club->getCanonicalName()}{/block}
|
||||
|
||||
|
@ -46,7 +46,7 @@
|
|||
<div style="float: left;">
|
||||
{tr("messages", $x->getCommentsCount())}
|
||||
</div>
|
||||
{var lastComment = $x->getLastComment()}
|
||||
{var $lastComment = $x->getLastComment()}
|
||||
<div n:if="$lastComment" class="avatar-list-item" style="float: right;">
|
||||
<div class="avatar">
|
||||
<a href="{$lastComment->getOwner()->getURL()}">
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
|
||||
{block content}
|
||||
|
||||
{var isMain = $mode === 'main'}
|
||||
{var isContacts = $mode === 'contacts'}
|
||||
{var isInterests = $mode === 'interests'}
|
||||
{var isAvatar = $mode === 'avatar'}
|
||||
{var $isMain = $mode === 'main'}
|
||||
{var $isContacts = $mode === 'contacts'}
|
||||
{var $isInterests = $mode === 'interests'}
|
||||
{var $isAvatar = $mode === 'avatar'}
|
||||
<div n:if="$user->hasPendingNumberChange()" class="msg">
|
||||
<b>Подтверждение номера телефона</b><br/>
|
||||
Введите код для подтверждения смены номера: <a href="/edit/verify_phone">ввести код</a>.
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
{extends "../@listView.xml"}
|
||||
{var perPage = 6} {* Why 6? Check User::_abstractRelationGenerator *}
|
||||
{var $perPage = 6} {* Why 6? Check User::_abstractRelationGenerator *}
|
||||
|
||||
{var act = $_GET["act"] ?? "friends"}
|
||||
{var $act = $_GET["act"] ?? "friends"}
|
||||
|
||||
{if $act == "incoming"}
|
||||
{var iterator = iterator_to_array($user->getFollowers($page))}
|
||||
{var count = $user->getFollowersCount()}
|
||||
{var $iterator = iterator_to_array($user->getFollowers($page))}
|
||||
{var $count = $user->getFollowersCount()}
|
||||
{elseif $act == "outcoming"}
|
||||
{var iterator = iterator_to_array($user->getSubscriptions($page))}
|
||||
{var count = $user->getSubscriptionsCount()}
|
||||
{var $iterator = iterator_to_array($user->getSubscriptions($page))}
|
||||
{var $count = $user->getSubscriptionsCount()}
|
||||
{else}
|
||||
{var iterator = iterator_to_array($user->getFriends($page))}
|
||||
{var count = $user->getFriendsCount()}
|
||||
{var $iterator = iterator_to_array($user->getFriends($page))}
|
||||
{var $count = $user->getFriendsCount()}
|
||||
{/if}
|
||||
|
||||
{block title}
|
||||
|
@ -113,7 +113,7 @@
|
|||
|
||||
{block actions}
|
||||
{if $x->getId() !== $thisUser->getId()}
|
||||
{var subStatus = $x->getSubscriptionStatus($thisUser)}
|
||||
{var $subStatus = $x->getSubscriptionStatus($thisUser)}
|
||||
{if $subStatus === 0}
|
||||
<form action="/setSub/user" method="post" class="profile_link_form">
|
||||
<input type="hidden" name="act" value="add" />
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{extends "../@listView.xml"}
|
||||
{var iterator = $user->getClubs($page, $admin)}
|
||||
{var count = $user->getClubCount($admin)}
|
||||
{var $iterator = $user->getClubs($page, $admin)}
|
||||
{var $count = $user->getClubCount($admin)}
|
||||
|
||||
{block title}
|
||||
{_groups}
|
||||
|
@ -73,7 +73,7 @@
|
|||
{/block}
|
||||
|
||||
{block actions}
|
||||
{var clubPinned = $thisUser->isClubPinned($x)}
|
||||
{var $clubPinned = $thisUser->isClubPinned($x)}
|
||||
{if $x->canBeModifiedBy($thisUser ?? NULL)}
|
||||
<div class="navigation" style="width: 140px;">
|
||||
<a class="link" href="{$x->getURL()}">
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
|
||||
{block content}
|
||||
|
||||
{var isMain = $mode === 'main'}
|
||||
{var isPrivacy = $mode === 'privacy'}
|
||||
{var isFinance = $mode === 'finance'}
|
||||
{var isFinanceTU = $mode === 'finance.top-up'}
|
||||
{var isInterface = $mode === 'interface'}
|
||||
{var $isMain = $mode === 'main'}
|
||||
{var $isPrivacy = $mode === 'privacy'}
|
||||
{var $isFinance = $mode === 'finance'}
|
||||
{var $isFinanceTU = $mode === 'finance.top-up'}
|
||||
{var $isInterface = $mode === 'interface'}
|
||||
|
||||
<div class="tabs">
|
||||
<div n:attr="id => ($isMain ? 'activetabs' : 'ki')" class="tab">
|
||||
|
|
|
@ -107,7 +107,7 @@
|
|||
<a n:if="OPENVK_ROOT_CONF['openvk']['preferences']['commerce'] && $user->getGiftCount() == 0" href="/gifts?act=pick&user={$user->getId()}" class="profile_link">{_send_gift}</a>
|
||||
<a n:if="$user->getPrivacyPermission('messages.write', $thisUser)" href="/im?sel={$user->getId()}" class="profile_link">{_"send_message"}</a>
|
||||
|
||||
{var subStatus = $user->getSubscriptionStatus($thisUser)}
|
||||
{var $subStatus = $user->getSubscriptionStatus($thisUser)}
|
||||
{if $subStatus === 0}
|
||||
<form action="/setSub/user" method="post" class="profile_link_form">
|
||||
<input type="hidden" name="act" value="add" />
|
||||
|
@ -141,7 +141,7 @@
|
|||
<a n:if="$user->getFollowersCount() > 0" href="/friends{$user->getId()}?act=incoming" class="profile_link">{tr("followers", $user->getFollowersCount())}</a>
|
||||
</div>
|
||||
<div n:if="isset($thisUser) && !$thisUser->prefersNotToSeeRating()" class="profile-hints">
|
||||
{var completeness = $user->getProfileCompletenessReport()}
|
||||
{var $completeness = $user->getProfileCompletenessReport()}
|
||||
|
||||
<div n:class="completeness-gauge, $completeness->total >= 100 ? completeness-gauge-gold">
|
||||
<div style="width: {$completeness->percent}%"></div>
|
||||
|
@ -174,7 +174,7 @@
|
|||
</div>
|
||||
<br />
|
||||
<div n:if="$user->getFriendsCount() > 0 && $user->getPrivacyPermission('friends.read', $thisUser ?? NULL)">
|
||||
{var friendCount = $user->getFriendsCount()}
|
||||
{var $friendCount = $user->getFriendsCount()}
|
||||
|
||||
<div class="content_title_expanded" onclick="hidePanel(this, {$friendCount});">
|
||||
{_"friends"}
|
||||
|
@ -215,7 +215,7 @@
|
|||
<div style="padding: 5px;">
|
||||
<div class="ovk-album" style="display: inline-block;" n:foreach="$albums as $album">
|
||||
<div style="text-align: center;float: left;height: 54pt;width: 100px;">
|
||||
{var cover = $album->getCoverPhoto()}
|
||||
{var $cover = $album->getCoverPhoto()}
|
||||
|
||||
<img
|
||||
src="{is_null($cover)?'/assets/packages/static/openvk/img/camera_200.png':$cover->getURLBySizeId('small')}"
|
||||
|
@ -284,7 +284,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div n:if="$user->getClubCount() > 0 && $user->getPrivacyPermission('groups.read', $thisUser ?? NULL)">
|
||||
{var clubsCount = $user->getClubCount()}
|
||||
{var $clubsCount = $user->getClubCount()}
|
||||
<div class="content_title_expanded" onclick="hidePanel(this, {$clubsCount})">
|
||||
{_"groups"}
|
||||
</div>
|
||||
|
@ -303,7 +303,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div n:if="$user->getMeetingCount() > 0 && $user->getPrivacyPermission('groups.read', $thisUser ?? NULL)">
|
||||
{var meetingCount = $user->getMeetingCount()}
|
||||
{var $meetingCount = $user->getMeetingCount()}
|
||||
<div class="content_title_expanded" onclick="hidePanel(this, {$meetingCount})">
|
||||
{_meetings}
|
||||
</div>
|
||||
|
@ -327,7 +327,7 @@
|
|||
<div class="right_big_block">
|
||||
<div class="page_info">
|
||||
<div n:if="!is_null($alert = $user->getAlert())" class="user-alert">{strpos($alert, "@") === 0 ? tr(substr($alert, 1)) : $alert}</div>
|
||||
{var thatIsThisUser = isset($thisUser) && $user->getId() == $thisUser->getId()}
|
||||
{var $thatIsThisUser = isset($thisUser) && $user->getId() == $thisUser->getId()}
|
||||
<div n:if="$thatIsThisUser" class="page_status_popup" id="status_editor" style="display: none;">
|
||||
<form name="status_popup_form" onsubmit="changeStatus(); return false;">
|
||||
<div style="margin-bottom: 10px;">
|
||||
|
@ -495,7 +495,7 @@
|
|||
</div>
|
||||
<div class="content_list long">
|
||||
<div class="cl_element" style="width: 25%;" n:foreach="$user->getGifts(1, 4) as $giftDescriptor">
|
||||
{var hideInfo = !is_null($thisUser) ? ($giftDescriptor->anon ? $thisUser->getId() !== $user->getId() : false) : false}
|
||||
{var $hideInfo = !is_null($thisUser) ? ($giftDescriptor->anon ? $thisUser->getId() !== $user->getId() : false) : false}
|
||||
<div class="cl_avatar">
|
||||
<a href="{$hideInfo ? 'javascript:false' : $giftDescriptor->sender->getURL()}">
|
||||
<img style="width: 70px; max-height: 70px;"
|
||||
|
|
|
@ -4,82 +4,86 @@
|
|||
{tr("user_banned", htmlentities($user->getFirstName()))|noescape}<br/>
|
||||
{_"user_banned_comment"} <b>{$user->getBanReason()}</b>.
|
||||
</p>
|
||||
<p n:if="isset($thisUser) && $thisUser->getChandlerUser()->can('access')->model('admin')->whichBelongsTo(NULL) || $thisUser->getChandlerUser()->can('write')->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)">
|
||||
<br />
|
||||
<a n:if="$thisUser->getChandlerUser()->can('access')->model('admin')->whichBelongsTo(NULL)" href="javascript:unbanUser()" class="button">{_unban_user_action}</a>
|
||||
<a n:if="$thisUser->getChandlerUser()->can('write')->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)" href="javascript:toggleBanInSupport()" class="button">
|
||||
{if $user->isBannedInSupport()}
|
||||
{_unban_in_support_user_action}
|
||||
{else}
|
||||
{_ban_in_support_user_action}
|
||||
{/if}
|
||||
</a>
|
||||
</p>
|
||||
{if isset($thisUser)}
|
||||
<p n:if="$thisUser->getChandlerUser()->can('access')->model('admin')->whichBelongsTo(NULL) || $thisUser->getChandlerUser()->can('write')->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)">
|
||||
<br />
|
||||
<a n:if="$thisUser->getChandlerUser()->can('access')->model('admin')->whichBelongsTo(NULL)" href="javascript:unbanUser()" class="button">{_unban_user_action}</a>
|
||||
<a n:if="$thisUser->getChandlerUser()->can('write')->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)" href="javascript:toggleBanInSupport()" class="button">
|
||||
{if $user->isBannedInSupport()}
|
||||
{_unban_in_support_user_action}
|
||||
{else}
|
||||
{_ban_in_support_user_action}
|
||||
{/if}
|
||||
</a>
|
||||
</p>
|
||||
{/if}
|
||||
</center>
|
||||
|
||||
<script n:if="isset($thisUser) && $thisUser->getChandlerUser()->can('access')->model('admin')->whichBelongsTo(NULL)">
|
||||
function unbanUser() {
|
||||
uUnbanMsgTxt = "Вы собираетесь разбанить пользователя " + {$user->getCanonicalName()} + ".";
|
||||
uUnbanMsgTxt += "<br/>Сейчас он заблокирован по причине: <strong>" + {$user->getBanReason()} + "</strong>.";
|
||||
|
||||
MessageBox("Разбанить " + {$user->getFirstName()}, uUnbanMsgTxt, ["Подтвердить", "Отмена"], [
|
||||
(function() {
|
||||
xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", "/admin/unban/" + {$user->getId()} + "?hash=" + {rawurlencode($csrfToken)}, true);
|
||||
xhr.onload = (function() {
|
||||
if(xhr.responseText.indexOf("success") === -1)
|
||||
MessageBox("Ошибка", "Не удалось разблокировать пользователя...", ["OK"], [Function.noop]);
|
||||
else
|
||||
MessageBox("Операция успешна", "Пользователь разблокирован", ["OK"], [Function.noop]);
|
||||
});
|
||||
xhr.send(null);
|
||||
}),
|
||||
Function.noop
|
||||
]);
|
||||
}
|
||||
</script>
|
||||
|
||||
<script n:if="isset($thisUser) && $thisUser->getChandlerUser()->can('write')->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)">
|
||||
{if $user->isBannedInSupport()}
|
||||
function toggleBanInSupport() {
|
||||
uBanMsgTxt = "Вы собираетесь разблокировать в поддержке пользователя " + {$user->getCanonicalName()} + ".";
|
||||
uBanMsgTxt += "<br/>Сейчас он заблокирован по причине <strong>" + {$user->getBanInSupportReason()} + "</strong>.";
|
||||
|
||||
MessageBox("Разблокировать в поддержке " + {$user->getFirstName()}, uBanMsgTxt, ["Подтвердить", "Отмена"], [
|
||||
{if isset($thisUser)}
|
||||
<script n:if="$thisUser->getChandlerUser()->can('access')->model('admin')->whichBelongsTo(NULL)">
|
||||
function unbanUser() {
|
||||
uUnbanMsgTxt = "Вы собираетесь разбанить пользователя " + {$user->getCanonicalName()} + ".";
|
||||
uUnbanMsgTxt += "<br/>Сейчас он заблокирован по причине: <strong>" + {$user->getBanReason()} + "</strong>.";
|
||||
|
||||
MessageBox("Разбанить " + {$user->getFirstName()}, uUnbanMsgTxt, ["Подтвердить", "Отмена"], [
|
||||
(function() {
|
||||
xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", "/admin/support/unban/" + {$user->getId()} + "?hash=" + {rawurlencode($csrfToken)}, true);
|
||||
xhr.open("GET", "/admin/unban/" + {$user->getId()} + "?hash=" + {rawurlencode($csrfToken)}, true);
|
||||
xhr.onload = (function() {
|
||||
if(xhr.responseText.indexOf("success") === -1)
|
||||
MessageBox("Ошибка", "Не удалось разблокировать пользователя в поддержке...", ["OK"], [Function.noop]);
|
||||
MessageBox("Ошибка", "Не удалось разблокировать пользователя...", ["OK"], [Function.noop]);
|
||||
else
|
||||
MessageBox("Операция успешна", "Пользователь разблокирован в поддержке", ["OK"], [Function.noop]);
|
||||
MessageBox("Операция успешна", "Пользователь разблокирован", ["OK"], [Function.noop]);
|
||||
});
|
||||
xhr.send(null);
|
||||
}),
|
||||
Function.noop
|
||||
]);
|
||||
}
|
||||
{else}
|
||||
function toggleBanInSupport() {
|
||||
uBanMsgTxt = "Вы собираетесь заблокировать в поддержке пользователя " + {$user->getCanonicalName()} + ".";
|
||||
uBanMsgTxt += "<br/><br/><b>Причина бана</b>: <input type='text' id='uBanMsgInput' placeholder='придумайте что-нибудь крутое' />";
|
||||
</script>
|
||||
|
||||
MessageBox("Заблокировать в поддержке " + {$user->getFirstName()}, uBanMsgTxt, ["Подтвердить", "Отмена"], [
|
||||
(function() {
|
||||
res = document.querySelector("#uBanMsgInput").value;
|
||||
xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", "/admin/support/ban/" + {$user->getId()} + "?reason=" + res + "&hash=" + {rawurlencode($csrfToken)}, true);
|
||||
xhr.onload = (function() {
|
||||
if(xhr.responseText.indexOf("success") === -1)
|
||||
MessageBox("Ошибка", "Не удалось заблокировать пользователя в поддержке...", ["OK"], [Function.noop]);
|
||||
else
|
||||
MessageBox("Операция успешна", "Пользователь заблокирован в поддержке", ["OK"], [Function.noop]);
|
||||
});
|
||||
xhr.send(null);
|
||||
}),
|
||||
Function.noop
|
||||
]);
|
||||
}
|
||||
{/if}
|
||||
</script>
|
||||
<script n:if="$thisUser->getChandlerUser()->can('write')->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)">
|
||||
{if $user->isBannedInSupport()}
|
||||
function toggleBanInSupport() {
|
||||
uBanMsgTxt = "Вы собираетесь разблокировать в поддержке пользователя " + {$user->getCanonicalName()} + ".";
|
||||
uBanMsgTxt += "<br/>Сейчас он заблокирован по причине <strong>" + {$user->getBanInSupportReason()} + "</strong>.";
|
||||
|
||||
MessageBox("Разблокировать в поддержке " + {$user->getFirstName()}, uBanMsgTxt, ["Подтвердить", "Отмена"], [
|
||||
(function() {
|
||||
xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", "/admin/support/unban/" + {$user->getId()} + "?hash=" + {rawurlencode($csrfToken)}, true);
|
||||
xhr.onload = (function() {
|
||||
if(xhr.responseText.indexOf("success") === -1)
|
||||
MessageBox("Ошибка", "Не удалось разблокировать пользователя в поддержке...", ["OK"], [Function.noop]);
|
||||
else
|
||||
MessageBox("Операция успешна", "Пользователь разблокирован в поддержке", ["OK"], [Function.noop]);
|
||||
});
|
||||
xhr.send(null);
|
||||
}),
|
||||
Function.noop
|
||||
]);
|
||||
}
|
||||
{else}
|
||||
function toggleBanInSupport() {
|
||||
uBanMsgTxt = "Вы собираетесь заблокировать в поддержке пользователя " + {$user->getCanonicalName()} + ".";
|
||||
uBanMsgTxt += "<br/><br/><b>Причина бана</b>: <input type='text' id='uBanMsgInput' placeholder='придумайте что-нибудь крутое' />";
|
||||
|
||||
MessageBox("Заблокировать в поддержке " + {$user->getFirstName()}, uBanMsgTxt, ["Подтвердить", "Отмена"], [
|
||||
(function() {
|
||||
res = document.querySelector("#uBanMsgInput").value;
|
||||
xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", "/admin/support/ban/" + {$user->getId()} + "?reason=" + res + "&hash=" + {rawurlencode($csrfToken)}, true);
|
||||
xhr.onload = (function() {
|
||||
if(xhr.responseText.indexOf("success") === -1)
|
||||
MessageBox("Ошибка", "Не удалось заблокировать пользователя в поддержке...", ["OK"], [Function.noop]);
|
||||
else
|
||||
MessageBox("Операция успешна", "Пользователь заблокирован в поддержке", ["OK"], [Function.noop]);
|
||||
});
|
||||
xhr.send(null);
|
||||
}),
|
||||
Function.noop
|
||||
]);
|
||||
}
|
||||
{/if}
|
||||
</script>
|
||||
{/if}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{extends "../@listView.xml"}
|
||||
{var iterator = $videos}
|
||||
{var count = $paginatorConf->count}
|
||||
{var page = $paginatorConf->page}
|
||||
{var $iterator = $videos}
|
||||
{var $count = $paginatorConf->count}
|
||||
{var $page = $paginatorConf->page}
|
||||
|
||||
{block title}{_"videos"} {$user->getCanonicalName()}{/block}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
{if $video->getType() === 0}
|
||||
<video width="610" src="{$video->getURL()}" controls></video>
|
||||
{else}
|
||||
{var driver = $video->getVideoDriver()}
|
||||
{var $driver = $video->getVideoDriver()}
|
||||
{if !$driver}
|
||||
Эта видеозапись не поддерживается в вашей версии OpenVK.
|
||||
{else}
|
||||
|
|
|
@ -27,9 +27,9 @@
|
|||
<div style="float: left; min-height: 100px; width: 32%;">
|
||||
<h4>{_actions}</h4>
|
||||
{if isset($thisUser)}
|
||||
{var canDelete = $post->canBeDeletedBy($thisUser)}
|
||||
{var $canDelete = $post->canBeDeletedBy($thisUser)}
|
||||
{if $thisUser->getId() != $post->getOwner()->getId()}
|
||||
{var canReport = true}
|
||||
{var $canReport = true}
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{if $attachment instanceof \openvk\Web\Models\Entities\Photo}
|
||||
{if !$attachment->isDeleted()}
|
||||
{var link = "/photo" . ($attachment->isAnonymous() ? ("s/" . base_convert((string) $attachment->getId(), 10, 32)) : $attachment->getPrettyId())}
|
||||
{var $link = "/photo" . ($attachment->isAnonymous() ? ("s/" . base_convert((string) $attachment->getId(), 10, 32)) : $attachment->getPrettyId())}
|
||||
<a href="{$link}">
|
||||
<img class="media" src="{$attachment->getURLBySizeId('normal')}" alt="{$attachment->getDescription()}" />
|
||||
</a>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{var author = $comment->getOwner()}
|
||||
{var $author = $comment->getOwner()}
|
||||
{var $Club = openvk\Web\Models\Entities\Club::class}
|
||||
{var postId = $comment->getTarget() instanceof \openvk\Web\Models\Entities\Post ? $comment->getTarget()->getId() : NULL}
|
||||
{var $postId = $comment->getTarget() instanceof \openvk\Web\Models\Entities\Post ? $comment->getTarget()->getId() : NULL}
|
||||
|
||||
<a name="cid={$comment->getId()}"></a>
|
||||
<table border="0" style="font-size: 11px;" class="post comment" id="_comment{$comment->getId()}" data-comment-id="{$comment->getId()}" data-owner-id="{$author->getId()}" data-from-group="{$comment->getOwner() instanceof $Club}" n:attr="data-post-id => $postId">
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<h4 n:if="$showTitle ?? true">{_comments} ({$count})</h4>
|
||||
|
||||
<div n:ifset="$thisUser">
|
||||
{var commentsURL = "/al_comments/create/$model/" . $parent->getId()}
|
||||
{var club = $parent instanceof \openvk\Web\Models\Entities\Post && $parent->getTargetWall() < 0 ? (new openvk\Web\Models\Repositories\Clubs)->get(abs($parent->getTargetWall())) : $club}
|
||||
{var $commentsURL = "/al_comments/create/$model/" . $parent->getId()}
|
||||
{var $club = $parent instanceof \openvk\Web\Models\Entities\Post && $parent->getTargetWall() < 0 ? (new openvk\Web\Models\Repositories\Clubs)->get(abs($parent->getTargetWall())) : $club}
|
||||
{if !$readOnly}
|
||||
{include "textArea.xml", route => $commentsURL, postOpts => false, graffiti => (bool) ovkGetQuirk("comments.allow-graffiti"), club => $club}
|
||||
{/if}
|
||||
|
@ -16,17 +16,6 @@
|
|||
{include "paginator.xml", conf => (object) ["page" => $page, "count" => $count, "amount" => sizeof($comments), "perPage" => 10]}
|
||||
</div>
|
||||
{else}
|
||||
<!-- {if $model === "photos"}
|
||||
<p>Будьте первым, кто оставит комментарий к этой фотографии</p>
|
||||
{elseif $model === "posts"}
|
||||
<p>Будьте первым, кто оставит комментарий к этой записи</p>
|
||||
{elseif $model === "notes"}
|
||||
<p>Будьте первым, кто оставит комментарий к этой заметке</p>
|
||||
{elseif $model === "videos"}
|
||||
<p>Будьте первым, кто оставит комментарий к этой видеозаписи</p>
|
||||
{else}
|
||||
<p>Будьте первым кто оставит комментарий к этой дичи!</p>
|
||||
{/if} -->
|
||||
{_comments_tip}
|
||||
{/if}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{var post = $notification->getModel(0)}
|
||||
{var user = $notification->getModel(1)}
|
||||
{var $post = $notification->getModel(0)}
|
||||
{var $user = $notification->getModel(1)}
|
||||
|
||||
<a href="{$user->getURL()}"><b>{$user->getCanonicalName()}</b></a>
|
||||
{$notification->getDateTime()} {_nt_liked_yours}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{var post = $notification->getModel(0)}
|
||||
{var user = $notification->getModel(1)}
|
||||
{var $post = $notification->getModel(0)}
|
||||
{var $user = $notification->getModel(1)}
|
||||
|
||||
<a href="{$user->getURL()}"><b>{$user->getCanonicalName()}</b></a>
|
||||
{$notification->getDateTime()} {_nt_shared_yours}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{var user = $notification->getModel(1)}
|
||||
{var $user = $notification->getModel(1)}
|
||||
|
||||
<a href="{$user->getURL()}"><b>{$user->getCanonicalName()}</b></a>
|
||||
{$notification->getDateTime()} {_nt_commented_yours} {include under}: "{$notification->getData()}".
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{extends "@default.xml"}
|
||||
{var post = $notification->getModel(0)}
|
||||
{var $post = $notification->getModel(0)}
|
||||
|
||||
{block under}
|
||||
{_nt_yours_feminitive_adjective} <a href="/note{$post->getPrettyId()}">{_nt_note_instrumental}</a>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{extends "@default.xml"}
|
||||
{var post = $notification->getModel(0)}
|
||||
{var $post = $notification->getModel(0)}
|
||||
|
||||
{block under}
|
||||
{_nt_yours_feminitive_adjective} <a href="/photo{$post->getPrettyId()}">{_nt_photo_instrumental}</a>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{extends "@default.xml"}
|
||||
{var post = $notification->getModel(0)}
|
||||
{var $post = $notification->getModel(0)}
|
||||
|
||||
{block under}
|
||||
{_nt_yours_adjective} <a href="/wall{$post->getPrettyId()}">{_nt_post_instrumental}</a> {_nt_from} {$post->getPublicationTime()}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{extends "@default.xml"}
|
||||
{var post = $notification->getModel(0)}
|
||||
{var $post = $notification->getModel(0)}
|
||||
|
||||
{block under}
|
||||
{_nt_yours_adjective} <a href="/video{$post->getPrettyId()}">{_video}</a>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{extends "@default.xml"}
|
||||
{var post = $notification->getModel(0)}
|
||||
{var $post = $notification->getModel(0)}
|
||||
|
||||
{block under}
|
||||
{_nt_yours_adjective} <a href="/topic{$post->getPrettyId()}">{_nt_topic_instrumental}</a>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{var post = $notification->getModel(0)}
|
||||
{var user = $notification->getModel(1)}
|
||||
{var $post = $notification->getModel(0)}
|
||||
{var $user = $notification->getModel(1)}
|
||||
|
||||
<a href="{$user->getURL()}"><b>{$user->getCanonicalName()}</b></a>
|
||||
{$notification->getDateTime()} {_nt_written_on_your_wall}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{var club = $notification->getModel(0)}
|
||||
{var user = $notification->getModel(1)}
|
||||
{var $club = $notification->getModel(0)}
|
||||
{var $user = $notification->getModel(1)}
|
||||
|
||||
<a href="{$user->getURL()}"><b>{$user->getCanonicalName()}</b></a>
|
||||
{_nt_made_you_admin}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{var gift = $notification->getModel(0)}
|
||||
{var sender = $notification->getModel(1)}
|
||||
{var $gift = $notification->getModel(0)}
|
||||
{var $sender = $notification->getModel(1)}
|
||||
|
||||
<a href="{$sender->getURL()}"><b>{$sender->getCanonicalName()}</b></a> отправил вам {$notification->getDateTime()} подарок.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{var sender = $notification->getModel(1)}
|
||||
{var value = (int) explode(" ", $notification->getData(), 2)[0]}
|
||||
{var message = explode(" ", $notification->getData(), 2)[1]}
|
||||
{var $sender = $notification->getModel(1)}
|
||||
{var $value = (int) explode(" ", $notification->getData(), 2)[0]}
|
||||
{var $message = explode(" ", $notification->getData(), 2)[1]}
|
||||
|
||||
<a href="{$sender->getURL()}"><b>{$sender->getCanonicalName()}</b></a> {_transferred_to_you} {tr("points_amount", $value)}.
|
||||
{if !empty($message)}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{var sender = $notification->getModel(1)}
|
||||
{var value = (int) explode(" ", $notification->getData(), 2)[0]}
|
||||
{var message = explode(" ", $notification->getData(), 2)[1]}
|
||||
{var $sender = $notification->getModel(1)}
|
||||
{var $value = (int) explode(" ", $notification->getData(), 2)[0]}
|
||||
{var $message = explode(" ", $notification->getData(), 2)[1]}
|
||||
|
||||
<a href="{$sender->getURL()}"><b>{$sender->getCanonicalName()}</b></a> {_increased_your_rating_by} {$value}%.
|
||||
{if !empty($message)}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{var microblogEnabled = isset($thisUser) ? $thisUser->hasMicroblogEnabled() : false}
|
||||
{var $microblogEnabled = isset($thisUser) ? $thisUser->hasMicroblogEnabled() : false}
|
||||
|
||||
{if $microblogEnabled}
|
||||
{include "post/microblogpost.xml", post => $post, diff => $diff, commentSection => $commentSection}
|
||||
{include "post/microblogpost.xml", post => $post, commentSection => $commentSection}
|
||||
{else}
|
||||
{include "post/oldpost.xml", post => $post, diff => $diff}
|
||||
{include "post/oldpost.xml", post => $post}
|
||||
{/if}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{var author = $post->getOwner()}
|
||||
{var comments = $post->getLastComments(3)}
|
||||
{var commentsCount = $post->getCommentsCount()}
|
||||
{var $author = $post->getOwner()}
|
||||
{var $comments = $post->getLastComments(3)}
|
||||
{var $commentsCount = $post->getCommentsCount()}
|
||||
|
||||
{var commentTextAreaId = $post === null ? rand(1,300) : $post->getId()}
|
||||
{var $commentTextAreaId = $post === null ? rand(1,300) : $post->getId()}
|
||||
|
||||
<table border="0" style="font-size: 11px;" n:class="post, !$compact ? post-divider, $post->isExplicit() ? post-nsfw">
|
||||
<tbody>
|
||||
|
@ -18,8 +18,8 @@
|
|||
<a href="{$author->getURL()}"><b>{$author->getCanonicalName()}</b></a>
|
||||
<img n:if="$author->isVerified()" class="name-checkmark" src="/assets/packages/static/openvk/img/checkmark.png">
|
||||
{if ($onWallOf ?? false) &&!$post->isPostedOnBehalfOfGroup() && $post->getOwnerPost() !== $post->getTargetWall()}
|
||||
{var wallId = $post->getTargetWall()}
|
||||
{var wallURL = $wallId > -1 ? "/id$wallId" : "/club" . abs($wallId)}
|
||||
{var $wallId = $post->getTargetWall()}
|
||||
{var $wallURL = $wallId > -1 ? "/id$wallId" : "/club" . abs($wallId)}
|
||||
на
|
||||
<a href="{$wallURL}">
|
||||
<b>
|
||||
|
@ -68,7 +68,7 @@
|
|||
! Этот пост был размещён за взятку.
|
||||
</div>
|
||||
<div n:if="$post->isSigned()" class="post-signature">
|
||||
{var actualAuthor = $post->getOwner(false)}
|
||||
{var $actualAuthor = $post->getOwner(false)}
|
||||
<span>
|
||||
{_author}:
|
||||
<a href="{$actualAuthor->getURL()}">
|
||||
|
@ -91,7 +91,7 @@
|
|||
</a>
|
||||
|
||||
{if !($forceNoLike ?? false)}
|
||||
{var liked = $post->hasLikeFrom($thisUser)}
|
||||
{var $liked = $post->hasLikeFrom($thisUser)}
|
||||
<a href="/wall{$post->getPrettyId()}/like?hash={rawurlencode($csrfToken)}" class="post-like-button" data-liked="{(int) $liked}" data-likes="{$post->getLikesCount()}">
|
||||
<div class="heart" id="{if $liked}liked{/if}"></div>
|
||||
<span class="likeCnt">{if $post->getLikesCount() > 0}{$post->getLikesCount()}{/if}</span>
|
||||
|
@ -106,8 +106,8 @@
|
|||
{include "../comment.xml", comment => $comment, $compact => true}
|
||||
{/foreach}
|
||||
<div n:ifset="$thisUser" id="commentTextArea{$commentTextAreaId}" n:attr="style => ($commentsCount == 0 ? 'display: none;')" class="commentsTextFieldWrap">
|
||||
{var commentsURL = "/al_comments/create/posts/" . $post->getId()}
|
||||
{var club = is_null($club) ? ($post->getTargetWall() < 0 ? (new openvk\Web\Models\Repositories\Clubs)->get(abs($post->getTargetWall())) : NULL) : $club}
|
||||
{var $commentsURL = "/al_comments/create/posts/" . $post->getId()}
|
||||
{var $club = is_null($club) ? ($post->getTargetWall() < 0 ? (new openvk\Web\Models\Repositories\Clubs)->get(abs($post->getTargetWall())) : NULL) : $club}
|
||||
{include "../textArea.xml", route => $commentsURL, postOpts => false, graffiti => (bool) ovkGetQuirk("comments.allow-graffiti"), post => $post, club => $club}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{var author = $post->getOwner()}
|
||||
{var $author = $post->getOwner()}
|
||||
|
||||
<table border="0" style="font-size: 11px;" n:class="post, $post->isExplicit() ? post-nsfw">
|
||||
<tbody>
|
||||
|
@ -15,8 +15,8 @@
|
|||
<img n:if="$author->isVerified()" class="name-checkmark" src="/assets/packages/static/openvk/img/checkmark.png">
|
||||
{$post->isPostedOnBehalfOfGroup() ? tr("post_writes_g") : ($author->isFemale() ? tr("post_writes_f") : tr("post_writes_m"))}
|
||||
{if ($onWallOf ?? false) &&!$post->isPostedOnBehalfOfGroup() && $post->getOwnerPost() !== $post->getTargetWall()}
|
||||
{var wallId = $post->getTargetWall()}
|
||||
{var wallURL = $wallId > -1 ? "/id$wallId" : "/club" . abs($wallId)}
|
||||
{var $wallId = $post->getTargetWall()}
|
||||
{var $wallURL = $wallId > -1 ? "/id$wallId" : "/club" . abs($wallId)}
|
||||
на
|
||||
<a href="{$wallURL}">
|
||||
<b>
|
||||
|
@ -50,7 +50,7 @@
|
|||
! Этот пост был размещён за взятку.
|
||||
</div>
|
||||
<div n:if="$post->isSigned()" class="post-signature">
|
||||
{var actualAuthor = $post->getOwner(false)}
|
||||
{var $actualAuthor = $post->getOwner(false)}
|
||||
<span>
|
||||
{_author}:
|
||||
<a href="{$actualAuthor->getURL()}">
|
||||
|
@ -92,7 +92,7 @@
|
|||
</a>
|
||||
|
||||
<div n:if="!($forceNoLike ?? false)" class="like_wrap">
|
||||
{var liked = $post->hasLikeFrom($thisUser)}
|
||||
{var $liked = $post->hasLikeFrom($thisUser)}
|
||||
<a href="/wall{$post->getPrettyId()}/like?hash={rawurlencode($csrfToken)}" class="post-like-button" data-liked="{(int) $liked}" data-likes="{$post->getLikesCount()}">
|
||||
<div class="heart" id="{if $liked}liked{/if}"></div>
|
||||
<span class="likeCnt">{if $post->getLikesCount() > 0}{$post->getLikesCount()}{/if}</span>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{php if(!isset($GLOBALS["textAreaCtr"])) $GLOBALS["textAreaCtr"] = 10;}
|
||||
{var textAreaId = ($post ?? NULL) === null ? (++$GLOBALS["textAreaCtr"]) : $post->getId()}
|
||||
{var $textAreaId = ($post ?? NULL) === null ? (++$GLOBALS["textAreaCtr"]) : $post->getId()}
|
||||
|
||||
<div id="write" style="padding: 5px 0;" onfocusin="expand_wall_textarea({$textAreaId});">
|
||||
<form action="{$route}" method="post" enctype="multipart/form-data" style="margin:0;">
|
||||
|
@ -12,7 +12,7 @@
|
|||
{_attachment}: <span>(unknown)</span>
|
||||
</div>
|
||||
<div n:if="$postOpts ?? true" class="post-opts">
|
||||
{var anonEnabled = OPENVK_ROOT_CONF['openvk']['preferences']['wall']['anonymousPosting']['enable']}
|
||||
{var $anonEnabled = OPENVK_ROOT_CONF['openvk']['preferences']['wall']['anonymousPosting']['enable']}
|
||||
|
||||
{if !is_null($thisUser) && !is_null($club ?? NULL) && $owner < 0}
|
||||
{if $club->canBeModifiedBy($thisUser)}
|
||||
|
|
|
@ -71,6 +71,8 @@ routes:
|
|||
handler: "User->twoFactorAuthSettings"
|
||||
- url: "/settings/2fa/disable"
|
||||
handler: "User->disableTwoFactorAuth"
|
||||
- url: "/settings/reset_theme"
|
||||
handler: "User->resetThemepack"
|
||||
- url: "/coins_transfer"
|
||||
handler: "User->coinsTransfer"
|
||||
- url: "/increase_social_credits"
|
||||
|
@ -121,8 +123,10 @@ routes:
|
|||
handler: "Wall->delete"
|
||||
- url: "/wall{num}_{num}/pin"
|
||||
handler: "Wall->pin"
|
||||
- url: "/blob_{text}/{text}.{text}"
|
||||
- url: "/blob_{text}/{?path}.{text}"
|
||||
handler: "Blob->file"
|
||||
placeholders:
|
||||
path: "[A-z0-9\\-_\\/]{3,}"
|
||||
- url: "/themepack/{text}/{?version}/{?resClass}/{?any}"
|
||||
handler: "Themepacks->resource"
|
||||
placeholders:
|
||||
|
@ -301,6 +305,8 @@ routes:
|
|||
handler: "About->robotsTxt"
|
||||
- url: "/humans.txt"
|
||||
handler: "About->humansTxt"
|
||||
- url: "/dev"
|
||||
handler: "About->dev"
|
||||
- url: "/{?shortCode}"
|
||||
handler: "UnknownTextRouteStrategy->delegate"
|
||||
placeholders:
|
||||
|
|
Binary file not shown.
BIN
Web/static/audio/notify.mp3
Normal file
BIN
Web/static/audio/notify.mp3
Normal file
Binary file not shown.
|
@ -2,7 +2,7 @@
|
|||
/* Design belongs to Pavel Durov & VK Group */
|
||||
|
||||
.post {
|
||||
padding: 5px 0 5px 0;
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
.post-divider {
|
||||
|
@ -12,7 +12,7 @@
|
|||
.post-author {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
padding: 0 3px 3px 3px;
|
||||
padding: 0 3px 3px;
|
||||
}
|
||||
|
||||
.post-author .date {
|
||||
|
@ -25,7 +25,7 @@
|
|||
}
|
||||
|
||||
.post-content .text {
|
||||
padding: 0 4px 0 4px;
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
.post-menu {
|
||||
|
@ -37,7 +37,7 @@
|
|||
}
|
||||
|
||||
.comment {
|
||||
padding: 5px 0 0 0;
|
||||
padding: 5px 0 0;
|
||||
border-top: 1px #ddd solid;
|
||||
}
|
||||
|
||||
|
@ -46,16 +46,16 @@
|
|||
}
|
||||
|
||||
.repost-icon {
|
||||
background: url('/assets/packages/static/openvk/img/published.gif') no-repeat 0px 0px;
|
||||
background: url('/assets/packages/static/openvk/img/published.gif') no-repeat 0 0;
|
||||
height: 12px;
|
||||
margin: 2px 3px 0px;
|
||||
margin: 2px 3px 0;
|
||||
width: 11px;
|
||||
}
|
||||
|
||||
.heart {
|
||||
background: url('/assets/packages/static/openvk/img/like.gif') no-repeat 1px 0px;
|
||||
background: url('/assets/packages/static/openvk/img/like.gif') no-repeat 1px 0;
|
||||
height: 10px;
|
||||
margin: 2px 3px 0px;
|
||||
margin: 2px 3px 0;
|
||||
width: 11px;
|
||||
float: none;
|
||||
opacity: 0.4;
|
||||
|
@ -73,24 +73,25 @@
|
|||
opacity: 0.4 !important;
|
||||
}
|
||||
|
||||
.post-share-button, .post-like-button {
|
||||
.post-share-button,
|
||||
.post-like-button {
|
||||
display: flex;
|
||||
padding: 2px;
|
||||
border-radius: 2px;
|
||||
transition-duration: 0.2s;
|
||||
}
|
||||
|
||||
.post-share-button:hover, .post-like-button:hover {
|
||||
.post-share-button:hover,
|
||||
.post-like-button:hover {
|
||||
background-color: rgb(240, 240, 240);
|
||||
}
|
||||
|
||||
.post-author .delete {
|
||||
float: right;
|
||||
display: inline-block;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
overflow: auto;
|
||||
background: url("/assets/packages/static/openvk/img/input_clear.gif") no-repeat 0px 0px;
|
||||
background: url("/assets/packages/static/openvk/img/input_clear.gif") no-repeat 0 0;
|
||||
opacity: 0.1;
|
||||
transition-duration: 0.3s;
|
||||
}
|
||||
|
@ -101,11 +102,10 @@
|
|||
|
||||
.post-author .pin {
|
||||
float: right;
|
||||
display: inline-block;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
overflow: auto;
|
||||
background: url("/assets/packages/static/openvk/img/pin.png") no-repeat 0px 0px;
|
||||
background: url("/assets/packages/static/openvk/img/pin.png") no-repeat 0 0;
|
||||
opacity: 0.1;
|
||||
transition-duration: 0.3s;
|
||||
}
|
||||
|
@ -117,7 +117,7 @@
|
|||
.expand_button {
|
||||
background-color: #eee;
|
||||
width: 100%;
|
||||
display: inline-block;;
|
||||
display: inline-block;
|
||||
height: 30px;
|
||||
line-height: 28px;
|
||||
text-align: center;
|
||||
|
|
|
@ -13,12 +13,6 @@ body {
|
|||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
span {
|
||||
padding: 0 0 2px;
|
||||
color: gray;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.nobold,
|
||||
nobold {
|
||||
font-weight: normal;
|
||||
|
@ -48,9 +42,9 @@ p {
|
|||
position: relative;
|
||||
width: 791px;
|
||||
height: 45px;
|
||||
background: url('../img/header.png');
|
||||
background-repeat: no-repeat;
|
||||
background-position: 0;
|
||||
background: url('../img/header.png');
|
||||
}
|
||||
|
||||
.page_custom_header {
|
||||
|
@ -59,7 +53,7 @@ p {
|
|||
|
||||
#page_act {
|
||||
border-bottom: 1px solid #d5dde6;
|
||||
padding: 2px 10px 5px 10px;
|
||||
padding: 2px 10px 5px;
|
||||
color: #2B587A;
|
||||
width: 608px;
|
||||
margin-left: -10px;
|
||||
|
@ -95,8 +89,8 @@ p {
|
|||
display: inline-block;
|
||||
height: 29px;
|
||||
padding: 11px 4px 0 7px;
|
||||
background-size: 1.5px 41px;
|
||||
background: url('../img/divider.png') no-repeat;
|
||||
background-size: 1.5px 41px;
|
||||
}
|
||||
|
||||
.header_navigation .link a {
|
||||
|
@ -164,7 +158,6 @@ p {
|
|||
padding: 3px 3px 3px 6px;
|
||||
text-decoration: none;
|
||||
border-top: 1px solid #fff;
|
||||
/* fix */
|
||||
color: #000;
|
||||
}
|
||||
|
||||
|
@ -184,17 +177,17 @@ p {
|
|||
|
||||
.wrap1 {
|
||||
border: 1px solid #EBF0F4;
|
||||
border-top: 0px;
|
||||
border-top: 0;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.wrap2 {
|
||||
border-right: 1px solid #F6F8FA;
|
||||
border-top: 0px;
|
||||
border-top: 0;
|
||||
}
|
||||
|
||||
.page_yellowheader {
|
||||
padding: 4px 10px 4px;
|
||||
padding: 4px 10px;
|
||||
font-weight: bold;
|
||||
background: url('../img/header_yellow.png') repeat-x;
|
||||
background-color: #EEE5B8;
|
||||
|
@ -405,7 +398,7 @@ table {
|
|||
.page_status {
|
||||
font-weight: normal;
|
||||
font-size: 11px;
|
||||
padding: 3px 1px 3px;
|
||||
padding: 3px 1px;
|
||||
color: #000;
|
||||
width: 380px;
|
||||
height: auto !important;
|
||||
|
@ -442,9 +435,9 @@ table {
|
|||
outline: none;
|
||||
white-space: nowrap;
|
||||
background: #595959;
|
||||
background-position: 0px -16px;
|
||||
background-position: 0 -16px;
|
||||
color: #fff;
|
||||
padding: 4px 8px 4px;
|
||||
padding: 4px 8px;
|
||||
text-shadow: 0 1px 0 #686868;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
|
@ -477,7 +470,7 @@ input[type=radio] {
|
|||
outline: none;
|
||||
cursor: pointer;
|
||||
vertical-align: middle;
|
||||
margin: 4px 3px 3px 3px;
|
||||
margin: 4px 3px 3px;
|
||||
}
|
||||
|
||||
input[type=checkbox] {
|
||||
|
@ -520,17 +513,13 @@ input[type=radio]:checked {
|
|||
width: 200px;
|
||||
}
|
||||
|
||||
.right_big_block {
|
||||
width: 399px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.content_title_expanded {
|
||||
background-image: url('../img/flex_arrow_open2.png');
|
||||
background-repeat: no-repeat;
|
||||
background-color: #e6e6e6;
|
||||
border-top: #8B8B8B solid 1px;
|
||||
padding: 3px 8px 3px 24px;
|
||||
margin-top: 5px;
|
||||
font-weight: bold;
|
||||
color: #626262;
|
||||
font-size: 11px;
|
||||
|
@ -554,7 +543,6 @@ input[type=radio]:checked {
|
|||
|
||||
.content_subtitle {
|
||||
background-color: #F0F0F0;
|
||||
padding: 0;
|
||||
display: block;
|
||||
font-size: 11px;
|
||||
border-bottom: 1px solid #EEEEEE;
|
||||
|
@ -568,7 +556,7 @@ input[type=radio]:checked {
|
|||
}
|
||||
|
||||
.content-withouttop {
|
||||
padding-top: 0px;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
input[type="text"],
|
||||
|
@ -595,8 +583,8 @@ h4 {
|
|||
color: #45688E;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
margin: 0px;
|
||||
padding: 0px 0px 3px;
|
||||
margin: 0;
|
||||
padding: 0 0 3px;
|
||||
font-family: verdana, arial, sans-serif;
|
||||
}
|
||||
|
||||
|
@ -619,7 +607,7 @@ h4 {
|
|||
border-top: #8B8B8B solid 1px;
|
||||
border-bottom: #ECECEC solid 1px;
|
||||
font-size: 11px;
|
||||
padding: 3px 5px 3px;
|
||||
padding: 3px 5px;
|
||||
line-height: 125%;
|
||||
}
|
||||
|
||||
|
@ -769,7 +757,7 @@ span {
|
|||
}
|
||||
|
||||
.content_list .cl_element .cl_avatar {
|
||||
padding: 7px 7px 0 7px;
|
||||
padding: 7px 7px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
@ -807,13 +795,6 @@ table.User {
|
|||
width: 603px;
|
||||
}
|
||||
|
||||
.container_gray .content {
|
||||
background: #fff;
|
||||
padding: 5px;
|
||||
border: #DEDEDE solid 1px;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
border-bottom: 1px solid #707070;
|
||||
padding: 0 10px;
|
||||
|
@ -832,7 +813,7 @@ table.User {
|
|||
display: inline-block;
|
||||
padding: 5px 10px;
|
||||
margin-right: 3px;
|
||||
border-radius: 3px 3px 0px 0px;
|
||||
border-radius: 3px 3px 0 0;
|
||||
}
|
||||
|
||||
.tab:hover {
|
||||
|
@ -995,11 +976,6 @@ table.User {
|
|||
color: #404036;
|
||||
}
|
||||
|
||||
.messenger-app--messages,
|
||||
.messenger-app--input {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.messenger-app--messages,
|
||||
.messenger-app--input {
|
||||
padding: 10px 70px;
|
||||
|
@ -1021,11 +997,6 @@ table.User {
|
|||
margin-bottom: 1.2rem;
|
||||
}
|
||||
|
||||
.messenger-app--messages---message .ava,
|
||||
.messenger-app--input>.ava {
|
||||
max-width: 64px;
|
||||
}
|
||||
|
||||
.messenger-app--messages---message .ava,
|
||||
.messenger-app--input>.ava {
|
||||
width: 52px;
|
||||
|
@ -1074,6 +1045,7 @@ table.User {
|
|||
box-sizing: border-box;
|
||||
padding: 0 10px;
|
||||
width: calc(100% - 128px);
|
||||
float: right;
|
||||
}
|
||||
|
||||
.messenger-app--input---messagebox textarea {
|
||||
|
@ -1083,10 +1055,6 @@ table.User {
|
|||
margin-bottom: 8px !important;
|
||||
}
|
||||
|
||||
.messenger-app--input---messagebox {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.messenger-app--input .blocked {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
@ -1190,16 +1158,16 @@ textarea {
|
|||
|
||||
#faqhead {
|
||||
background: #fbf3c3;
|
||||
margin: 0px 5px 0px 5px;
|
||||
margin: 0 5px;
|
||||
padding: 5px;
|
||||
font-weight: bold;
|
||||
border: 1px solid #d7cf9e;
|
||||
border-bottom: 0px;
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
#faqcontent {
|
||||
background: #fafafa;
|
||||
margin: 0px 5px 10px 5px;
|
||||
margin: 0 5px 10px;
|
||||
padding: 5px 5px 5px 10px;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
@ -1307,12 +1275,6 @@ body.scrolled .toTop:hover {
|
|||
vertical-align: super;
|
||||
}
|
||||
|
||||
.ugc-table tr>td:nth-of-type(2) {
|
||||
display: block;
|
||||
width: 270px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.ugc-table.slim tr>td:nth-of-type(1) {
|
||||
width: unset;
|
||||
}
|
||||
|
@ -1378,9 +1340,9 @@ body.scrolled .toTop:hover {
|
|||
}
|
||||
|
||||
.heart {
|
||||
background: url('/assets/packages/static/openvk/img/like.gif') no-repeat 1px 0px;
|
||||
background: url('/assets/packages/static/openvk/img/like.gif') no-repeat 1px 0;
|
||||
height: 10px;
|
||||
margin: 2px 3px 0px;
|
||||
margin: 2px 3px 0;
|
||||
width: 11px;
|
||||
float: left;
|
||||
opacity: 0.4;
|
||||
|
@ -1400,10 +1362,6 @@ body.scrolled .toTop:hover {
|
|||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
.content_title_expanded {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.page-wrap {
|
||||
border-bottom: solid 1px #C3CAD2;
|
||||
border-left: solid 1px #DAE1E8;
|
||||
|
@ -1411,33 +1369,12 @@ body.scrolled .toTop:hover {
|
|||
padding: 10px;
|
||||
}
|
||||
|
||||
.wrap1 {
|
||||
width: auto;
|
||||
border: 1px solid #EBF0F4;
|
||||
border-top: 0px;
|
||||
}
|
||||
|
||||
.wrap2 {
|
||||
border-right: 1px solid #F6F8FA;
|
||||
border-top: 0px;
|
||||
}
|
||||
|
||||
#wrapH {
|
||||
border-right: solid 1px #EAEEF3;
|
||||
border-left: solid 1px #EAEEF3;
|
||||
}
|
||||
|
||||
#wrapHI {
|
||||
border-right: solid 1px #D5DDE6;
|
||||
border-left: solid 1px #D5DDE6;
|
||||
}
|
||||
|
||||
.ugc-table td {
|
||||
vertical-align: top !important;
|
||||
font-size: 11px;
|
||||
line-height: 13px;
|
||||
margin: 0px;
|
||||
padding: 1px 0px 1px 0px;
|
||||
margin: 0;
|
||||
padding: 1px 0;
|
||||
}
|
||||
|
||||
.label {
|
||||
|
@ -1457,47 +1394,44 @@ body.scrolled .toTop:hover {
|
|||
}
|
||||
|
||||
#basicInfo {
|
||||
padding: 5px 0px 15px 8px;
|
||||
padding: 5px 0 15px 8px;
|
||||
}
|
||||
|
||||
.accountInfo {
|
||||
padding: 0px;
|
||||
margin: 0px 0px 0px 8px;
|
||||
padding: 0;
|
||||
margin: 0 0 0 8px;
|
||||
border-bottom: solid 1px #DAE1E8;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.profileName {
|
||||
/* width: 225px; */
|
||||
color: #45688E;
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
margin: 0px;
|
||||
/* padding: 2px 5px 0px 0px; */
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.profileName h2 {
|
||||
color: #45688E;
|
||||
font-size: 13px;
|
||||
padding-bottom: 0px;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.notes_titles {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.written {
|
||||
background: url('/assets/packages/static/openvk/img/note.gif') no-repeat 0px 1px;
|
||||
padding: 0px 0px 6px 22px;
|
||||
background: url('/assets/packages/static/openvk/img/note.gif') no-repeat 0 1px;
|
||||
padding: 0 0 6px 22px;
|
||||
}
|
||||
|
||||
.written a {
|
||||
display: block;
|
||||
padding: 0px 0px 1px 0px;
|
||||
padding: 0 0 1px;
|
||||
}
|
||||
|
||||
.notes_titles small {
|
||||
|
@ -1517,8 +1451,8 @@ body.scrolled .toTop:hover {
|
|||
}
|
||||
|
||||
.right_big_block h4 {
|
||||
margin: 1px 0px 0px;
|
||||
padding: 4px 0px 2px !important;
|
||||
margin: 1px 0 0;
|
||||
padding: 4px 0 2px !important;
|
||||
}
|
||||
|
||||
.knowledgeBaseArticle ul {
|
||||
|
@ -1577,7 +1511,7 @@ body.scrolled .toTop:hover {
|
|||
align-content: center;
|
||||
display: flex;
|
||||
padding: 2px;
|
||||
box-shadow: inset 0 0 0px 1px #ccc, inset 0 0 0px 2px #fff;
|
||||
box-shadow: inset 0 0 0 1px #ccc, inset 0 0 0 2px #fff;
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
|
@ -1648,17 +1582,26 @@ body.scrolled .toTop:hover {
|
|||
color: #58462a;
|
||||
}
|
||||
|
||||
.group-alert {
|
||||
margin-bottom: 8px;
|
||||
padding: 4px;
|
||||
border: 1px solid #c3a476;
|
||||
font-weight: 900;
|
||||
background-color: #f3ddbd;
|
||||
color: #58462a;
|
||||
}
|
||||
|
||||
.knowledgeBaseArticle {
|
||||
margin-top: -11px;
|
||||
/* this is very stupid fix but nah */
|
||||
}
|
||||
|
||||
.avatar-list {
|
||||
padding: 4px 8px 4px 8px;
|
||||
padding: 4px 8px;
|
||||
}
|
||||
|
||||
.avatar-list-item {
|
||||
padding: 4px 0 4px 0;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.avatar-list-item::after {
|
||||
|
@ -1763,9 +1706,9 @@ body.scrolled .toTop:hover {
|
|||
outline: none;
|
||||
white-space: nowrap;
|
||||
background: #595959;
|
||||
background-position: 0px -16px;
|
||||
background-position: 0 -16px;
|
||||
color: #fff;
|
||||
padding: 4px 8px 4px;
|
||||
padding: 4px 8px;
|
||||
text-shadow: 0 1px 0 #686868;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
|
@ -1810,7 +1753,7 @@ body.scrolled .toTop:hover {
|
|||
height: 16px;
|
||||
width: 16px;
|
||||
overflow: auto;
|
||||
background: url("/assets/packages/static/openvk/img/pin.png") no-repeat 0px 0px;
|
||||
background: url("/assets/packages/static/openvk/img/pin.png") no-repeat 0 0;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
|
@ -1858,7 +1801,7 @@ body.scrolled .toTop:hover {
|
|||
background: #f7f7f7;
|
||||
border-bottom: solid 1px #DAE1E8;
|
||||
border-top: solid 1px #45688E;
|
||||
padding: 4px 6px 5px 6px;
|
||||
padding: 4px 6px 5px;
|
||||
}
|
||||
|
||||
.note_header .note_title {
|
||||
|
@ -1867,18 +1810,18 @@ body.scrolled .toTop:hover {
|
|||
font-weight: bold;
|
||||
line-height: 15px;
|
||||
margin: 0;
|
||||
padding: 0 0 1px 0;
|
||||
padding: 0 0 1px;
|
||||
}
|
||||
|
||||
.note_footer {
|
||||
border-top: 1px solid #ddd;
|
||||
clear: both;
|
||||
margin-top: 10px;
|
||||
padding: 0px 2px 0px 6px;
|
||||
padding: 0 2px 0 6px;
|
||||
}
|
||||
|
||||
.comments_count {
|
||||
padding: 5px 0px 0px 0px;
|
||||
padding: 5px 0 0;
|
||||
}
|
||||
|
||||
.groups_options {
|
||||
|
@ -1917,7 +1860,7 @@ table td[width="120"] {
|
|||
}
|
||||
|
||||
.profile_thumb {
|
||||
padding: 0px 10px 0px 0px;
|
||||
padding: 0 10px 0 0;
|
||||
width: 50px;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
|
@ -1941,23 +1884,6 @@ table td[width="120"] {
|
|||
padding: 3px 7px;
|
||||
}
|
||||
|
||||
#gp_container span {
|
||||
display: block;
|
||||
margin: 10px 0 15px;
|
||||
}
|
||||
|
||||
#gp_container h4 {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.container_gray .content:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.group_info {
|
||||
padding: 0 0 0 5px !important;
|
||||
}
|
||||
|
||||
.mb_tab#active {
|
||||
background-color: #898989;
|
||||
}
|
||||
|
@ -1970,15 +1896,8 @@ table td[width="120"] {
|
|||
color: white;
|
||||
}
|
||||
|
||||
.profile_thumb {
|
||||
padding: 0px 10px 0px 0px;
|
||||
width: 50px;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.border-block {
|
||||
box-shadow: inset 0px 0 0px 1px #b6bfca, inset 0px 0 0px 10px #d8dfe7;
|
||||
box-shadow: inset 0 0 0 1px #b6bfca, inset 0 0 0 10px #d8dfe7;
|
||||
width: 300px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
@ -1986,3 +1905,12 @@ table td[width="120"] {
|
|||
.center {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
#votesBalance {
|
||||
margin-top: 50px;
|
||||
padding: 7px;
|
||||
background-color: #f6f6f6;
|
||||
border-bottom: 1.5px solid #707070;
|
||||
text-align: center;
|
||||
user-select: none;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
createjs.Sound.registerSound("/assets/packages/static/openvk/audio/Bruh.mp3", "notification");
|
||||
createjs.Sound.registerSound("/assets/packages/static/openvk/audio/notify.mp3", "notification");
|
||||
|
||||
function __actualPlayNotifSound() {
|
||||
createjs.Sound.play("notification");
|
||||
|
|
|
@ -117,3 +117,8 @@ function setupWallPostInputHandlers(id) {
|
|||
// textArea.style.height = (newHeight > originalHeight ? (newHeight + boost) : originalHeight) + "px";
|
||||
});
|
||||
}
|
||||
|
||||
u("#write > form").on("keydown", function(event) {
|
||||
if(event.ctrlKey && event.keyCode === 13)
|
||||
this.submit();
|
||||
});
|
||||
|
|
|
@ -2,7 +2,33 @@ Function.noop = () => {};
|
|||
|
||||
var _n_counter = 0;
|
||||
|
||||
function NewNotification(title, body, avatar = null, callback = () => {}, time = 5000) {
|
||||
var _activeWindow = true;
|
||||
|
||||
const _pageTitle = u("title").nodes[0].innerText;
|
||||
|
||||
var counter = 0;
|
||||
|
||||
/* this fucking dumb shit is broken :c
|
||||
|
||||
window.addEventListener('focus', () => {
|
||||
_activeWindow = true;
|
||||
closeAllNotifications();
|
||||
});
|
||||
|
||||
window.addEventListener('blur', () => {_activeWindow = false});
|
||||
|
||||
function closeAllNotifications() {
|
||||
var notifications = u(".notifications_global_wrap").nodes[0].children;
|
||||
for (var i = 0; i < notifications.length; i++) {
|
||||
setTimeout(() => {
|
||||
console.log(i);
|
||||
notifications.item(i).classList.add('disappears');
|
||||
setTimeout(() => {notifications.item(i).remove()}, 500).bind(this);
|
||||
}, 5000).bind(this);
|
||||
}
|
||||
} */
|
||||
|
||||
function NewNotification(title, body, avatar = null, callback = () => {}, time = 5000, count = true) {
|
||||
if(avatar != null) {
|
||||
avatar = '<avatar>' +
|
||||
'<img src="' + avatar + '">' +
|
||||
|
@ -39,8 +65,15 @@ function NewNotification(title, body, avatar = null, callback = () => {}, time =
|
|||
getPrototype().addClass('disappears');
|
||||
setTimeout(() => {getPrototype().remove()}, 500);
|
||||
}
|
||||
|
||||
setTimeout(() => {__closeNotification()}, time);
|
||||
|
||||
if(count == true) {
|
||||
counter++;
|
||||
document.title = `(${counter}) ${_pageTitle}`;
|
||||
}
|
||||
|
||||
/* if(_activeWindow == true) { */
|
||||
setTimeout(() => {__closeNotification()}, time);
|
||||
/* } */
|
||||
|
||||
notification.children('notification_title').children('a.close').on('click', function(e) {
|
||||
__closeNotification();
|
||||
|
|
BIN
Web/static/video/rendering.apng
Normal file
BIN
Web/static/video/rendering.apng
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.8 KiB |
BIN
Web/static/video/rendering.ogv
Normal file
BIN
Web/static/video/rendering.ogv
Normal file
Binary file not shown.
|
@ -16,7 +16,9 @@
|
|||
"erusev/parsedown": "dev-master",
|
||||
"bhaktaraz/php-rss-generator": "dev-master",
|
||||
"ext-simplexml": "*",
|
||||
"symfony/console": "5.4.x-dev"
|
||||
"symfony/console": "5.4.x-dev",
|
||||
"wapmorgan/morphos": "dev-master",
|
||||
"ext-sodium": "*"
|
||||
},
|
||||
"minimum-stability": "dev"
|
||||
}
|
||||
|
|
79
composer.lock
generated
79
composer.lock
generated
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "878bd996183ccbb15637a7399ba03ab9",
|
||||
"content-hash": "63feb555e36a6e7ab5a0a5ec71adecdd",
|
||||
"packages": [
|
||||
{
|
||||
"name": "al/emoji-detector",
|
||||
|
@ -2222,6 +2222,80 @@
|
|||
},
|
||||
"time": "2018-09-26T17:10:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "wapmorgan/morphos",
|
||||
"version": "dev-master",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/wapmorgan/Morphos.git",
|
||||
"reference": "ec18034d4a439139902c769a64bb67e59e3402a8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/wapmorgan/Morphos/zipball/ec18034d4a439139902c769a64bb67e59e3402a8",
|
||||
"reference": "ec18034d4a439139902c769a64bb67e59e3402a8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-mbstring": "*",
|
||||
"php": ">=5.4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.8"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-readline": "For using interactive version of script"
|
||||
},
|
||||
"default-branch": true,
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/English/functions.php",
|
||||
"src/Russian/functions.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"morphos\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Sergey Vanyushin",
|
||||
"email": "wapmorgan@gmail.com",
|
||||
"role": "developer"
|
||||
}
|
||||
],
|
||||
"description": "A morphological solution for Russian and English language written completely in PHP. Provides classes to inflect personal names, geographical names, decline and pluralize nouns, generate cardinal and ordinal numerals, spell out money amounts and time.",
|
||||
"homepage": "http://morphos.io",
|
||||
"keywords": [
|
||||
"Numerals",
|
||||
"adjectives",
|
||||
"cardinal",
|
||||
"declension",
|
||||
"english",
|
||||
"geographical names",
|
||||
"human-friendly",
|
||||
"inflection",
|
||||
"language",
|
||||
"money",
|
||||
"morphology",
|
||||
"nouns",
|
||||
"ordinal",
|
||||
"personal names",
|
||||
"pluralization",
|
||||
"russian",
|
||||
"spelling",
|
||||
"time"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/wapmorgan/Morphos/issues",
|
||||
"source": "https://github.com/wapmorgan/Morphos/tree/master"
|
||||
},
|
||||
"time": "2021-11-22T09:15:18+00:00"
|
||||
},
|
||||
{
|
||||
"name": "whichbrowser/parser",
|
||||
"version": "dev-master",
|
||||
|
@ -2356,7 +2430,8 @@
|
|||
"vearutop/php-obscene-censor-rus": 20,
|
||||
"erusev/parsedown": 20,
|
||||
"bhaktaraz/php-rss-generator": 20,
|
||||
"symfony/console": 20
|
||||
"symfony/console": 20,
|
||||
"wapmorgan/morphos": 20
|
||||
},
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
|
|
|
@ -2,17 +2,23 @@ chandler:
|
|||
debug: true
|
||||
websiteUrl: null
|
||||
rootApp: "openvk"
|
||||
|
||||
|
||||
preferences:
|
||||
appendExtension: "xhtml"
|
||||
adminUrl: "/chandlerd"
|
||||
exposeChandler: true
|
||||
|
||||
|
||||
extensions:
|
||||
path: null
|
||||
allEnabled: false
|
||||
|
||||
database:
|
||||
dsn: "mysql:unix_socket=/var/run/mysql/mysql.sock;dbname=openvk"
|
||||
user: "root"
|
||||
password: "justMonika"
|
||||
|
||||
|
||||
security:
|
||||
secret: "081906e04f2921e48751fbc5df44dbbcd7f6ecba065ade3d8ea28034cb8d6db24da10965845b5f3376847674e3bce61b5c0e439d12eef3c00d30f3b953657cac"
|
||||
sessionDuration: 14
|
||||
csrfProtection: "permissive"
|
||||
extendedValidation: false
|
||||
|
|
105
install/automated/common/openvk.template.yml
Normal file
105
install/automated/common/openvk.template.yml
Normal file
|
@ -0,0 +1,105 @@
|
|||
openvk:
|
||||
debug: true
|
||||
appearance:
|
||||
name: "FreeBSD Instance"
|
||||
motd: "Yet another OpenVK instance"
|
||||
|
||||
preferences:
|
||||
femaleGenderPriority: true
|
||||
nginxCacheTime: 120
|
||||
uploads:
|
||||
disableLargeUploads: false
|
||||
mode: "basic"
|
||||
api:
|
||||
maxFilesPerDomain: 10
|
||||
maxFileSize: 25000000
|
||||
shortcodes:
|
||||
minLength: 3 # won't affect existing short urls or the ones set via admin panel
|
||||
forbiddenNames:
|
||||
- "index.php"
|
||||
photos:
|
||||
upgradeStructure: false
|
||||
security:
|
||||
requireEmail: false
|
||||
requirePhone: false
|
||||
forcePhoneVerification: false
|
||||
forceEmailVerification: false
|
||||
enableSu: true
|
||||
rateLimits:
|
||||
actions: 5
|
||||
time: 20
|
||||
maxViolations: 50
|
||||
maxViolationsAge: 120
|
||||
autoban: true
|
||||
registration:
|
||||
enable: true
|
||||
reason: "" # reason for disabling registration
|
||||
support:
|
||||
supportName: "Moderator"
|
||||
adminAccount: 1 # Change this ok
|
||||
fastAnswers:
|
||||
- "This is a list of quick answers to common questions for support. Post your responses here and agents can send it quickly with just 3 clicks"
|
||||
- "There can be as many answers as you want, but it is best to have a maximum of 10.\n\nYou can also remove all answers from the list to disable this feature"
|
||||
- "Good luck filling! If you are a regular support agent, inform the administrator that he forgot to fill the config"
|
||||
messages:
|
||||
strict: false
|
||||
wall:
|
||||
christian: false
|
||||
anonymousPosting:
|
||||
enable: false
|
||||
account: 100
|
||||
postSizes:
|
||||
maxSize: 60000
|
||||
processingLimit: 3000
|
||||
emojiProcessingLimit: 1000
|
||||
commerce: false
|
||||
menu:
|
||||
links:
|
||||
- name: "@left_menu_donate"
|
||||
url: "/donate"
|
||||
adPoster:
|
||||
enable: false
|
||||
src: "https://example.org/ad_poster.jpeg"
|
||||
caption: "Ad caption"
|
||||
link: "https://example.org/product.aspx?id=10&from=ovk"
|
||||
bellsAndWhistles:
|
||||
fartscroll: false
|
||||
testLabel: false
|
||||
defaultMobileTheme: ""
|
||||
|
||||
telemetry:
|
||||
plausible:
|
||||
enable: false
|
||||
domain: ""
|
||||
server: ""
|
||||
piwik:
|
||||
enable: false
|
||||
container: ""
|
||||
site: ""
|
||||
layer: "dataLayer"
|
||||
matomo:
|
||||
enable: false
|
||||
container: ""
|
||||
site: ""
|
||||
|
||||
credentials:
|
||||
smsc:
|
||||
enable: false
|
||||
client: ""
|
||||
secret: "SECRET_KEY_HERE"
|
||||
telegram:
|
||||
enable: false
|
||||
token: "TOKEN_HERE"
|
||||
helpdeskChat: ""
|
||||
eventDB:
|
||||
enable: true # Better enable this
|
||||
database:
|
||||
dsn: "mysql:unix_socket=/var/run/mysql/mysql.sock;dbname=openvk-eventdb"
|
||||
user: "root"
|
||||
password: "justMonika"
|
||||
notificationsBroker:
|
||||
enable: false
|
||||
kafka:
|
||||
addr: "127.0.0.1"
|
||||
port: 9092
|
||||
topic: "OvkEvents"
|
|
@ -1,10 +1,10 @@
|
|||
#!/bin/tcsh
|
||||
|
||||
##########################################################################################################\
|
||||
# OpenVK AutoInstallation Script for FreeBSD 12 # /( )` #
|
||||
# OpenVK AutoInstallation Script for FreeBSD 13 # /( )` #
|
||||
# ------------------------------------------------------------- # \ \___ / | #
|
||||
# # /- _ `-/ ' #
|
||||
# This script installs OpenVK on an empty FreeBSD 12 box. # (/\/ \ \ /\ #
|
||||
# This script installs OpenVK on an empty FreeBSD 13 box. # (/\/ \ \ /\ #
|
||||
# Copyright (c) 2020 OpenVK contributors # / / | ` \ #
|
||||
# ------------------------------------------------------------- # O O ) / | #
|
||||
# # `-^--'`< ' #
|
||||
|
@ -27,28 +27,27 @@ if ($? == 1) then
|
|||
endif
|
||||
|
||||
set osVer = `freebsd-version -r`
|
||||
if ($osVer !~ "12.*") then
|
||||
echo "Fatal Error: This installation supports only FreeBSD 12, but you have FreeBSD $osVer installed."
|
||||
if ($osVer !~ "13.*") then
|
||||
echo "Fatal Error: This installation supports only FreeBSD 13, but you have FreeBSD $osVer installed."
|
||||
exit 201
|
||||
endif
|
||||
|
||||
# Update system
|
||||
pkg update
|
||||
pkg upgrade
|
||||
cd /tmp
|
||||
mkdir ovkinstall
|
||||
cd ovkinstall
|
||||
|
||||
# Install programming languages and Git
|
||||
yes | pkg install git
|
||||
yes | pkg install php74
|
||||
yes | pkg install mod_php74 # will also install Apache2.4
|
||||
yes | pkg install php74-gd php74-mbstring php74-iconv php74-json php74-sodium php74-calendar php74-curl php74-brotli php74-zip php74-openssl php74-ctype php74-dom php74-fileinfo php74-PDO php74-pdo_mysql php74-sqlite3 php74-pdo_sqlite php74-sockets php74-tokenizer php74-opcache php74-posix php74-pecl-yaml php74-phar php74-filter php74-zlib php74-session
|
||||
# Install required packages
|
||||
yes | pkg install git php74 mod_php74 php74-gd php74-mbstring php74-iconv php74-json php74-sodium php74-calendar php74-curl php74-brotli php74-zip php74-openssl php74-ctype php74-dom php74-fileinfo php74-PDO php74-pdo_mysql php74-sqlite3 php74-pdo_sqlite php74-sockets php74-tokenizer php74-opcache php74-posix php74-pecl-yaml php74-phar php74-filter php74-zlib php74-session php74-simplexml node www/npm mysql80-server mysql80-client ffmpeg
|
||||
rehash
|
||||
|
||||
# Install package managers
|
||||
npm i -g yarn
|
||||
curl -LO https://getcomposer.org/installer
|
||||
php ./installer --install-dir=/bin --filename=composer --preview
|
||||
rm -f ./installer
|
||||
yes | pkg install node npm
|
||||
npm i -g yarn
|
||||
rehash
|
||||
|
||||
# Download OVK distro
|
||||
cd /tmp
|
||||
git clone https://github.com/openvk/openvk.git
|
||||
|
||||
# Install chandler
|
||||
|
@ -58,7 +57,7 @@ git clone https://github.com/openvk/chandler.git
|
|||
|
||||
cd chandler
|
||||
yes | composer install
|
||||
cp /tmp/openvk/install/automated/common/chandler.yml /opt/chandler/chandler.yml
|
||||
cp /tmp/ovkinstall/openvk/install/automated/common/chandler.yml /opt/chandler/chandler.yml
|
||||
chown -R www: .
|
||||
chmod -R 777 .
|
||||
|
||||
|
@ -75,7 +74,7 @@ cd /opt/chandler
|
|||
ln -s /opt/chandler/extensions/available/commitcaptcha /opt/chandler/extensions/enabled/commitcaptcha
|
||||
|
||||
# Install OpenVK
|
||||
cp -r /tmp/openvk /opt/chandler/extensions/available/openvk
|
||||
cp -r /tmp/ovkinstall/openvk /opt/chandler/extensions/available/openvk
|
||||
ln -s /opt/chandler/extensions/available/openvk /opt/chandler/extensions/enabled/openvk
|
||||
|
||||
cd ./extensions/available/openvk
|
||||
|
@ -84,36 +83,46 @@ yes | composer install
|
|||
cd Web/static/js
|
||||
yarn install
|
||||
|
||||
cp /tmp/openvk/install/automated/common/openvk.yml /opt/chandler/extensions/available/openvk/openvk.yml
|
||||
cp /tmp/ovkinstall/openvk/install/automated/common/openvk.template.yml /opt/chandler/extensions/available/openvk/openvk.yml
|
||||
|
||||
cd ../../../
|
||||
chown -R www: .
|
||||
chmod -R 777 .
|
||||
|
||||
# Install MySQL
|
||||
yes | pkg install mariadb105-server mariadb105-client
|
||||
# Setup databases
|
||||
sysrc mysql_enable="yes"
|
||||
service mysql-server start
|
||||
nohup /usr/local/libexec/mariadbd >& /dev/null & # service mysql-server start doesn't work
|
||||
sleep 15
|
||||
|
||||
# Mount databases
|
||||
cd /opt/chandler
|
||||
mysql < /tmp/openvk/install/automated/common/mk_db.sql
|
||||
mysql < /tmp/ovkinstall/openvk/install/automated/common/mk_db.sql
|
||||
mysql -p'justMonika' openvk < install/init-db.sql
|
||||
mysql -p'justMonika' openvk < /tmp/openvk/install/init-static-db.sql
|
||||
mysql -p'justMonika' openvk-eventdb < /tmp/openvk/install/init-event-db.sql
|
||||
mysql -p'justMonika' openvk < /tmp/ovkinstall/openvk/install/init-static-db.sql
|
||||
mysql -p'justMonika' openvk-eventdb < /tmp/ovkinstall/openvk/install/init-event-db.sql
|
||||
|
||||
cd /tmp/ovkinstall/openvk/install/sqls
|
||||
foreach migration (*.sql)
|
||||
mysql -p'justMonika' openvk < $migration
|
||||
end
|
||||
|
||||
# Change database settings
|
||||
echo "ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'justMonika'; FLUSH PRIVILEGES;" | mysql -p'justMonika';
|
||||
|
||||
sed -i'' -e 's:/var/run/mysql/mysql.sock:/tmp/mysql.sock:' /opt/chandler/chandler.yml
|
||||
sed -i'' -e 's:/var/run/mysql/mysql.sock:/tmp/mysql.sock:' /opt/chandler/extensions/available/openvk/openvk.yml
|
||||
|
||||
# Alias folders
|
||||
rm -rf /usr/local/www/apache24/data
|
||||
ln -s /opt/chandler/htdocs /usr/local/www/apache24/data
|
||||
|
||||
# Configure Apache
|
||||
cp /tmp/openvk/install/automated/common/httpd.conf /usr/local/etc/apache24/httpd.conf
|
||||
cp /tmp/openvk/install/automated/common/httpd-php.conf /usr/local/etc/apache24/Includes/php.conf
|
||||
cp /tmp/ovkinstall/openvk/install/automated/common/httpd.conf /usr/local/etc/apache24/httpd.conf
|
||||
cp /tmp/ovkinstall/openvk/install/automated/common/httpd-php.conf /usr/local/etc/apache24/Includes/php.conf
|
||||
sysrc apache24_enable="yes"
|
||||
service apache24 start
|
||||
|
||||
# Cleanup
|
||||
rm -rf /opt/ovkinstall
|
||||
|
||||
# Enjoy
|
||||
echo "~================= OpenVK 2 Installed =================~"
|
||||
echo " Use it: http://localhost:80/ "
|
|
@ -1 +1 @@
|
|||
ALTER TABLE groups ADD COLUMN administrators_list_display TINYINT(3) UNSIGNED NOT NULL DEFAULT 0;
|
||||
ALTER TABLE `groups` ADD COLUMN administrators_list_display TINYINT(3) UNSIGNED NOT NULL DEFAULT 0;
|
||||
|
|
|
@ -1 +1 @@
|
|||
ALTER TABLE groups ADD COLUMN owner_comment VARCHAR(36) AFTER owner;
|
||||
ALTER TABLE `groups` ADD COLUMN owner_comment VARCHAR(36) AFTER owner;
|
||||
|
|
|
@ -3,7 +3,7 @@ ALTER TABLE `profiles` ADD `activated` tinyint(3) NULL DEFAULT '1' AFTER `2fa_se
|
|||
CREATE TABLE IF NOT EXISTS `email_verifications` (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`profile` bigint(20) unsigned NOT NULL,
|
||||
`key` char(64) COLLATE utf8mb4_general_nopad_ci NOT NULL,
|
||||
`key` char(64) COLLATE utf8mb4_unicode_520_ci NOT NULL,
|
||||
`timestamp` bigint(20) unsigned NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_nopad_ci;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;
|
||||
|
|
1
install/sqls/00021-video-processing.sql
Normal file
1
install/sqls/00021-video-processing.sql
Normal file
|
@ -0,0 +1 @@
|
|||
ALTER TABLE `videos` ADD `processed` BOOLEAN NOT NULL DEFAULT FALSE AFTER `link`, ADD `last_checked` BIGINT UNSIGNED NOT NULL DEFAULT '0' AFTER `processed`;
|
1
install/sqls/00022-group-alerts.sql
Normal file
1
install/sqls/00022-group-alerts.sql
Normal file
|
@ -0,0 +1 @@
|
|||
ALTER TABLE `groups` ADD `alert` TEXT NULL DEFAULT NULL;
|
|
@ -558,6 +558,8 @@
|
|||
"points" = "Votes";
|
||||
"points_count" = "votes";
|
||||
"on_your_account" = "on your account";
|
||||
"top_up_your_account" = "Get more";
|
||||
"you_still_have_x_points" = "You have <b>$1</b> unused votes.";
|
||||
|
||||
"vouchers" = "Vouchers";
|
||||
"have_voucher" = "Have voucher";
|
||||
|
@ -779,6 +781,7 @@
|
|||
"error_new_password" = "New password does not match";
|
||||
"error_shorturl_incorrect" = "The short address has an incorrect format.";
|
||||
"error_repost_fail" = "Failed to share post";
|
||||
"error_data_too_big" = "Attribute '$1' must be at most $2 $3 long";
|
||||
|
||||
"forbidden" = "Access error";
|
||||
"forbidden_comment" = "This user's privacy settings do not allow you to look at his page.";
|
||||
|
@ -858,6 +861,8 @@
|
|||
"rules" = "Rules";
|
||||
"most_popular_groups" = "Most popular groups";
|
||||
"on_this_instance_are" = "On this instance are:";
|
||||
"about_links" = "Links";
|
||||
"instance_links" = "Instance links:";
|
||||
|
||||
"about_users_one" = "<b>1</b> user";
|
||||
"about_users_other" = "<b>$1</b> users";
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue