Merge branch 'master' into feature-reports

This commit is contained in:
Ilya Prokopenko 2022-04-24 12:17:35 +07:00 committed by GitHub
commit 1b469c6e60
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
102 changed files with 1022 additions and 598 deletions

View file

@ -38,6 +38,7 @@
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/console" /> <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/console" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-php80" /> <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-php80" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/service-contracts" /> <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/service-contracts" />
<excludeFolder url="file://$MODULE_DIR$/vendor/wapmorgan/morphos" />
</content> </content>
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />

View file

@ -39,6 +39,7 @@
<path value="$PROJECT_DIR$/vendor/symfony/console" /> <path value="$PROJECT_DIR$/vendor/symfony/console" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php80" /> <path value="$PROJECT_DIR$/vendor/symfony/polyfill-php80" />
<path value="$PROJECT_DIR$/vendor/symfony/service-contracts" /> <path value="$PROJECT_DIR$/vendor/symfony/service-contracts" />
<path value="$PROJECT_DIR$/vendor/wapmorgan/morphos" />
</include_path> </include_path>
</component> </component>
<component name="PhpProjectSharedConfiguration" php_language_level="7.4"> <component name="PhpProjectSharedConfiguration" php_language_level="7.4">

View file

@ -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: 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) * `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 ## Instances
* **[openvk.su](https://openvk.su/)** * **[openvk.su](https://openvk.su/)**
* **[openvk.uk](https://openvk.uk)** - official mirror of openvk.su (<https://t.me/openvkch/1609>) * **[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/) * [social.fetbuk.ru](http://social.fetbuk.ru/)
* [vepurovk.xyz](http://vepurovk.xyz/)
## Can I create my own OpenVK instance? ## 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). * 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 ```bash
git clone https://github.com/openvk/openvk /path/to/chandler/extensions/available/openvk 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 git clone https://github.com/openvk/commitcaptcha /path/to/chandler/extensions/available/commitcaptcha
``` ```
3. And enable them: 4. And enable them:
```bash ```bash
ln -s /path/to/chandler/extensions/available/commitcaptcha /path/to/chandler/extensions/enabled/ 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/ 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-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. Import `install/init-event-db.sql` to a **separate database** (Yandex.Clickhouse can also be used, highly recommended)
6. Copy `openvk-example.yml` to `openvk.yml` and change options to your liking 7. 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 OpenVK directory
8. Run `composer install` in commitcaptcha directory 9. Run `composer install` in commitcaptcha directory
9. Move to `Web/static/js` and execute `yarn install` 10. Move to `Web/static/js` and execute `yarn install`
10. Set `openvk` as your root app in `chandler.yml` 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): Once you are done, you can login as a system administrator on the network itself (no registration required):

View file

@ -2,23 +2,25 @@
_[English](README.md)_ _[English](README.md)_
**OpenVK** это попытка создать простую CMS, которая ~~косплеит~~ имитирует старый ВКонтакте. Представленный здесь код пока не стабилен. **OpenVK** - это попытка создать простую CMS, которая ~~косплеит~~ имитирует старый ВКонтакте. На данный момент представленный здесь исходный код проекта пока не является стабильным.
ВКонтакте принадлежит Павлу Дурову и VK Group. ВКонтакте принадлежит Павлу Дурову и VK Group.
Честно говоря, мы даже не знаем, работает ли она вообще. Однако, эта версия поддерживается, и мы будем рады принять ваши сообщения об ошибках [в нашем баг-трекере](https://github.com/openvk/openvk/projects/1). Вы также можете отправлять их через [вкладку "Помощь"](https://openvk.su/support?act=new) (для этого вам понадобится учетная запись OVK). Честно говоря, мы даже не знаем, работает ли она вообще. Однако, эта версия поддерживается, и мы будем рады принять ваши сообщения об ошибках [в нашем баг-трекере](https://github.com/openvk/openvk/projects/1). Вы также можете отправлять их через [вкладку "Помощь"](https://openvk.su/support?act=new) (для этого вам понадобится учетная запись OVK).
## Когда релиз? ## Когда выйдет релизная версия?
Мы выпустим OpenVK, как только он будет готов. На данный момент Вы можете: Мы выпустим OpenVK, как только он будет готов. На данный момент Вы можете:
* Сделать `git clone` master ветки этой репозитории (используйте `git pull` для обновления) * Склонировать master ветку репозитория командой `git clone` (используйте `git pull` для обновления)
* Взять готовую сборку OpenVK из [GitHub Actions](https://github.com/openvk/archive/actions/workflows/nightly.yml) * Взять готовую сборку OpenVK из [GitHub Actions](https://nightly.link/openvk/archive/workflows/nightly/master/OpenVK%20Archive.zip)
## Инстанции ## Инстанции
* **[openvk.su](https://openvk.su/)** * **[openvk.su](https://openvk.su/)**
* **[openvk.uk](https://openvk.uk)** - официальное зеркало openvk.su (<https://t.me/openvkch/1609>) * **[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/) * [social.fetbuk.ru](http://social.fetbuk.ru/)
* [vepurovk.xyz](http://vepurovk.xyz/)
## Могу ли я создать свою собственную инстанцию OpenVK? ## Могу ли я создать свою собственную инстанцию OpenVK?
@ -32,35 +34,41 @@ _[English](README.md)_
1. Установите PHP 7.4, веб-сервер, Composer, Node.js, Yarn и [Chandler](https://github.com/openvk/chandler) 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 ```bash
git clone https://github.com/openvk/openvk /path/to/chandler/extensions/available/openvk 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 git clone https://github.com/openvk/commitcaptcha /path/to/chandler/extensions/available/commitcaptcha
``` ```
3. И включите их: 4. И включите их:
```bash ```bash
ln -s /path/to/chandler/extensions/available/commitcaptcha /path/to/chandler/extensions/enabled/ 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/ 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-static-db.sql` в **ту же базу данных**, в которую вы установили Chandler, и импортируйте все SQL файлы из папки `install/sqls` в **ту же базу данных**
5. Импортируйте `install/init-event-db.sql` в **отдельную базу данных** (Яндекс.Clickhouse также может быть использован, настоятельно рекомендуется) 6. Импортируйте `install/init-event-db.sql` в **отдельную базу данных** (Яндекс.Clickhouse также может быть использован, настоятельно рекомендуется)
6. Скопируйте `openvk-example.yml` в `openvk.yml` и измените параметры 7. Скопируйте `openvk-example.yml` в `openvk.yml` и измените параметры под свои нужды
7. Запустите `composer install` в директории OpenVK 8. Запустите `composer install` в директории OpenVK
8. Запустите `composer install` в директории commitcaptcha 9. Запустите `composer install` в директории commitcaptcha
9. Перейдите в `Web/static/js` и выполните `yarn install` 10. Перейдите в `Web/static/js` и выполните `yarn install`
10. Установите `openvk` в качестве корневого приложения в файле `chandler.yml` 11. Установите `openvk` в качестве корневого приложения в файле `chandler.yml`
После этого вы можете войти как системный администратор в саму сеть (регистрация не требуется): После этого вы можете войти как системный администратор в саму сеть (регистрация не требуется):
* **Логин**: `admin@localhost.localdomain6` * **Логин**: `admin@localhost.localdomain6`
* **Пароль**: `admin` * **Пароль**: `admin`
* Перед использованием встроенной учетной записи рекомендуется сменить пароль. * Перед использованием встроенной учетной записи рекомендуется сменить пароль или отключить её.
💡Запутались? Полное руководство по установке доступно [здесь](https://docs.openvk.su/openvk_engine/centos8_installation/) (CentOS 8 [и](https://almalinux.org/ru/) [семейство](https://yum.oracle.com/oracle-linux-isos.html)). 💡Запутались? Полное руководство по установке доступно [здесь](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**. **Внимание**: баг-трекер, форум, телеграм- и matrix-чат являются публичными местами, и жалобы в OVK обслуживается волонтерами. Если вам нужно сообщить о чем-то, что не должно быть раскрыто широкой публике (например, сообщение об уязвимости), пожалуйста, свяжитесь с нами напрямую по этому адресу: **openvk [собака] tutanota [точка] com**.
<a href="https://codeberg.org/OpenVK/openvk"> <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> </a>

View file

@ -62,8 +62,26 @@ final class Users extends VKAPIRequestHandler
$response[$i]->photo_max_orig = $usr->getAvatarURL(); $response[$i]->photo_max_orig = $usr->getAvatarURL();
break; break;
case 'photo_max': case 'photo_max':
$response[$i]->photo_max = $usr->getAvatarURL(); $response[$i]->photo_max = $usr->getAvatarURL("original");
break; 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': case 'status':
if($usr->getStatus() != null) if($usr->getStatus() != null)
$response[$i]->status = $usr->getStatus(); $response[$i]->status = $usr->getStatus();

View file

@ -35,11 +35,42 @@ final class Wall extends VKAPIRequestHandler
"date" => $attachment->getPublicationTime()->timestamp(), "date" => $attachment->getPublicationTime()->timestamp(),
"id" => $attachment->getVirtualId(), "id" => $attachment->getVirtualId(),
"owner_id" => $attachment->getOwner()->getId(), "owner_id" => $attachment->getOwner()->getId(),
"sizes" => array([ "sizes" => array(
"height" => 500, // Для временного компросима оставляю статическое число. Если каждый раз обращаться к файлу за количеством пикселов, то наступает пuпuська полная с производительностью, так что пока так [
"url" => $attachment->getURL(), "height" => 2560,
"url" => $attachment->getURLBySizeId("normal"),
"type" => "m", "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" => "", "text" => "",
"has_tags" => false "has_tags" => false
@ -168,11 +199,42 @@ final class Wall extends VKAPIRequestHandler
"date" => $attachment->getPublicationTime()->timestamp(), "date" => $attachment->getPublicationTime()->timestamp(),
"id" => $attachment->getVirtualId(), "id" => $attachment->getVirtualId(),
"owner_id" => $attachment->getOwner()->getId(), "owner_id" => $attachment->getOwner()->getId(),
"sizes" => array([ "sizes" => array(
"height" => 500, // я ещё я заебался вставлять одинаковый код в два разных места [
"url" => $attachment->getURL(), "height" => 2560,
"url" => $attachment->getURLBySizeId("normal"),
"type" => "m", "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" => "", "text" => "",
"has_tags" => false "has_tags" => false

16
Vagrantfile vendored
View file

@ -1,16 +1,22 @@
# -*- mode: ruby -*- # -*- mode: ruby -*-
# vi: set ft=ruby : # vi: set ft=ruby :
Vagrant.configure("2") do |config| 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.network "forwarded_port", guest: 80, host: 4000
config.vm.synced_folder ".", "/.ovk_release"
config.vm.provider "virtualbox" do |vb| config.vm.provider "virtualbox" do |vb|
vb.gui = true vb.gui = true
vb.memory = "1024" vb.cpus = 4
vb.memory = "1568"
end end
config.vm.provision "shell", inline: "/bin/tcsh /.ovk_release/install/automated/freebsd-12/install" 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-13/install"
end end

View file

@ -347,5 +347,10 @@ class Club extends RowModel
return $this->getRecord()->website; return $this->getRecord()->website;
} }
function getAlert(): ?string
{
return $this->getRecord()->alert;
}
use Traits\TSubscribable; use Traits\TSubscribable;
} }

View file

@ -6,6 +6,8 @@ abstract class Media extends Postable
{ {
protected $fileExtension = "oct"; #octet stream xddd protected $fileExtension = "oct"; #octet stream xddd
protected $upperNodeReferenceColumnName = "owner"; protected $upperNodeReferenceColumnName = "owner";
protected $processingPlaceholder = NULL;
protected $processingTime = 30;
function __destruct() function __destruct()
{ {
@ -23,6 +25,11 @@ abstract class Media extends Postable
return OPENVK_ROOT . "/storage/"; return OPENVK_ROOT . "/storage/";
} }
protected function checkIfFileIsProcessed(): bool
{
throw new \LogicException("checkIfFileIsProcessed is not implemented");
}
abstract protected function saveFile(string $filename, string $hash): bool; abstract protected function saveFile(string $filename, string $hash): bool;
protected function pathFromHash(string $hash): string protected function pathFromHash(string $hash): string
@ -41,6 +48,10 @@ abstract class Media extends Postable
function getURL(): string function getURL(): string
{ {
if(!is_null($this->processingPlaceholder))
if(!$this->isProcessed())
return "/assets/packages/static/openvk/$this->processingPlaceholder.$this->fileExtension";
$hash = $this->getRecord()->hash; $hash = $this->getRecord()->hash;
switch(OPENVK_ROOT_CONF["openvk"]["preferences"]["uploads"]["mode"]) { switch(OPENVK_ROOT_CONF["openvk"]["preferences"]["uploads"]["mode"]) {
@ -55,7 +66,7 @@ abstract class Media extends Postable
case "server": case "server":
$settings = (object) OPENVK_ROOT_CONF["openvk"]["preferences"]["uploads"]["server"]; $settings = (object) OPENVK_ROOT_CONF["openvk"]["preferences"]["uploads"]["server"];
return ( return (
$settings->protocol . $settings->protocol ?? ovk_scheme() .
"://" . $settings->host . "://" . $settings->host .
$settings->path . $settings->path .
substr($hash, 0, 2) . "/$hash.$this->fileExtension" substr($hash, 0, 2) . "/$hash.$this->fileExtension"
@ -69,6 +80,26 @@ abstract class Media extends Postable
return $this->getRecord()->description; 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 function isDeleted(): bool
{ {
return (bool) $this->getRecord()->deleted; return (bool) $this->getRecord()->deleted;
@ -90,6 +121,16 @@ abstract class Media extends Postable
$this->stateChanges("hash", $hash); $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 function delete(bool $softly = true): void
{ {
$deleteQuirk = ovkGetQuirk("blobs.erase-upon-deletion"); $deleteQuirk = ovkGetQuirk("blobs.erase-upon-deletion");

View file

@ -55,16 +55,21 @@ trait TRichText
{ {
$contentColumn = property_exists($this, "overrideContentColumn") ? $this->overrideContentColumn : "content"; $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"]; $proc = iconv_strlen($this->getRecord()->{$contentColumn}) <= OPENVK_ROOT_CONF["openvk"]["preferences"]["wall"]["postSizes"]["processingLimit"];
if($html) { if($html) {
if($proc) { if($proc) {
$rel = $this->isAd() ? "sponsored" : "ugc"; $rel = $this->isAd() ? "sponsored" : "ugc";
$text = $this->formatLinks($text); $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("%([\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("%\[([A-Za-z0-9]++)\|((?:[\p{L&}\p{Lo} 0-9@]\p{Mn}?)++)\]%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_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); $text = $this->formatEmojis($text);
} }

View file

@ -1,5 +1,6 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
namespace openvk\Web\Models\Entities; namespace openvk\Web\Models\Entities;
use morphos\Gender;
use openvk\Web\Themes\{Themepack, Themepacks}; use openvk\Web\Themes\{Themepack, Themepacks};
use openvk\Web\Util\DateTime; use openvk\Web\Util\DateTime;
use openvk\Web\Models\RowModel; use openvk\Web\Models\RowModel;
@ -9,6 +10,7 @@ use openvk\Web\Models\Exceptions\InvalidUserNameException;
use Nette\Database\Table\ActiveRow; use Nette\Database\Table\ActiveRow;
use Chandler\Database\DatabaseConnection; use Chandler\Database\DatabaseConnection;
use Chandler\Security\User as ChandlerUser; use Chandler\Security\User as ChandlerUser;
use function morphos\Russian\inflectName;
class User extends RowModel class User extends RowModel
{ {
@ -167,12 +169,23 @@ class User extends RowModel
return $this->getFirstName() . $pseudo . $this->getLastName(); 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 function getCanonicalName(): string
{ {
if($this->getRecord()->deleted) if($this->getRecord()->deleted)
return "DELETED"; return "DELETED";
else else
return $this->getFirstName() . ' ' . $this->getLastName(); return $this->getFirstName() . " " . $this->getLastName();
} }
function getPhone(): ?string function getPhone(): ?string

View file

@ -15,6 +15,8 @@ class Video extends Media
protected $tableName = "videos"; protected $tableName = "videos";
protected $fileExtension = "ogv"; protected $fileExtension = "ogv";
protected $processingPlaceholder = "video/rendering";
protected function saveFile(string $filename, string $hash): bool protected function saveFile(string $filename, string $hash): bool
{ {
if(!Shell::commandAvailable("ffmpeg") || !Shell::commandAvailable("ffprobe")) if(!Shell::commandAvailable("ffmpeg") || !Shell::commandAvailable("ffprobe"))
@ -37,7 +39,7 @@ class Video extends Media
throw new \DomainException("$filename does not contain any meaningful video streams"); throw new \DomainException("$filename does not contain any meaningful video streams");
try { try {
if(!is_dir($dirId = $this->pathFromHash($hash))) if(!is_dir($dirId = dirname($this->pathFromHash($hash))))
mkdir($dirId); mkdir($dirId);
$dir = $this->getBaseDir(); $dir = $this->getBaseDir();
@ -54,6 +56,22 @@ class Video extends Media
return true; 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 function getName(): string
{ {
return $this->getRecord()->name; return $this->getRecord()->name;
@ -83,6 +101,9 @@ class Video extends Media
function getThumbnailURL(): string function getThumbnailURL(): string
{ {
if($this->getType() === Video::TYPE_DIRECT) { 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()); return preg_replace("%\.[A-z]++$%", ".gif", $this->getURL());
} else { } else {
return $this->getVideoDriver()->getThumbnailURL(); return $this->getVideoDriver()->getThumbnailURL();

View file

@ -45,7 +45,7 @@ class Clubs
function getPopularClubs(): \Traversable 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); $entries = DatabaseConnection::i()->getConnection()->query($query);
foreach($entries as $entry) foreach($entries as $entry)

View file

@ -13,7 +13,7 @@ Move-Item $file $temp
# video stub logic was implicitly deprecated, so we start processing at once # 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 -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" Move-Item $temp2 "$dir$hashT/$hash.ogv"
Remove-Item $temp Remove-Item $temp

View file

@ -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 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 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 rm -rf $3${4:0:2}/$4.ogv
mv "/tmp/ffmOi$tmpfile.ogv" $3${4:0:2}/$4.ogv mv "/tmp/ffmOi$tmpfile.ogv" $3${4:0:2}/$4.ogv

View file

@ -126,4 +126,11 @@ final class AboutPresenter extends OpenVKPresenter
header("Location: https://github.com/openvk/openvk#readme"); header("Location: https://github.com/openvk/openvk#readme");
exit; exit;
} }
function renderDev(): void
{
header("HTTP/1.1 302 Found");
header("Location: https://docs.openvk.su/");
exit;
}
} }

View file

@ -17,20 +17,23 @@ final class BlobPresenter extends OpenVKPresenter
function renderFile(/*string*/ $dir, string $name, string $format) function renderFile(/*string*/ $dir, string $name, string $format)
{ {
$dir = $this->getDirName($dir); $dir = $this->getDirName($dir);
$name = preg_replace("%[^a-zA-Z0-9_\-]++%", "", $name); $base = realpath(OPENVK_ROOT . "/storage/$dir");
$path = OPENVK_ROOT . "/storage/$dir/$name.$format"; $path = realpath(OPENVK_ROOT . "/storage/$dir/$name.$format");
if(!file_exists($path)) { if(!$path) # Will also check if file exists since realpath fails on ENOENT
$this->notFound(); $this->notFound();
} else { else if(strpos($path, $path) !== 0) # Prevent directory traversal and storage container escape
if(isset($_SERVER["HTTP_IF_NONE_MATCH"])) $this->notFound();
if(isset($_SERVER["HTTP_IF_NONE_MATCH"]))
exit(header("HTTP/1.1 304 Not Modified")); exit(header("HTTP/1.1 304 Not Modified"));
header("Content-Type: " . mime_content_type($path)); header("Content-Type: " . mime_content_type($path));
header("Content-Size: " . filesize($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) . "\""); header("ETag: W/\"" . hash_file("snefru", $path) . "\"");
readfile($path); readfile($path);
exit; exit;
}
} }
} }

View file

@ -72,6 +72,8 @@ final class PhotosPresenter extends OpenVKPresenter
if($_SERVER["REQUEST_METHOD"] === "POST") { if($_SERVER["REQUEST_METHOD"] === "POST") {
if(empty($this->postParam("name"))) if(empty($this->postParam("name")))
$this->flashFail("err", tr("error"), tr("error_segmentation")); $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 = new Album;
$album->setOwner(isset($club) ? $club->getId() * -1 : $this->user->id); $album->setOwner(isset($club) ? $club->getId() * -1 : $this->user->id);
@ -100,6 +102,9 @@ final class PhotosPresenter extends OpenVKPresenter
$this->template->album = $album; $this->template->album = $album;
if($_SERVER["REQUEST_METHOD"] === "POST") { 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->setName(empty($this->postParam("name")) ? $album->getName() : $this->postParam("name"));
$album->setDescription(empty($this->postParam("desc")) ? NULL : $this->postParam("desc")); $album->setDescription(empty($this->postParam("desc")) ? NULL : $this->postParam("desc"));
$album->setEdited(time()); $album->setEdited(time());

View file

@ -481,6 +481,22 @@ final class UserPresenter extends OpenVKPresenter
$this->flashFail("succ", tr("information_-1"), tr("two_factor_authentication_disabled_message")); $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 function renderCoinsTransfer(): void
{ {
$this->assertUserLoggedIn(); $this->assertUserLoggedIn();

View file

@ -303,8 +303,6 @@ final class WallPresenter extends OpenVKPresenter
function renderPost(int $wall, int $post_id): void function renderPost(int $wall, int $post_id): void
{ {
$this->assertUserLoggedIn();
$post = $this->posts->getPostById($wall, $post_id); $post = $this->posts->getPostById($wall, $post_id);
if(!$post || $post->isDeleted()) if(!$post || $post->isDeleted())
$this->notFound(); $this->notFound();

View file

@ -4,7 +4,7 @@
</div> </div>
<div class="container_gray"> <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} {if sizeof($data) > 0}
<div class="content" n:foreach="$data as $dat"> <div class="content" n:foreach="$data as $dat">

View file

@ -3,7 +3,7 @@
{block wrap} {block wrap}
<div class="ovk-lw-container"> <div class="ovk-lw-container">
<div class="ovk-lw--list"> <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} {if sizeof($data) > 0}
<table n:foreach="$data as $dat" border="0" style="font-size:11px;" class="post"> <table n:foreach="$data as $dat" border="0" style="font-size:11px;" class="post">

View file

@ -1,5 +1,4 @@
{var instance_name = OPENVK_ROOT_CONF['openvk']['appearance']['name']} {var $instance_name = OPENVK_ROOT_CONF['openvk']['appearance']['name']}
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>

View file

@ -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> <!DOCTYPE html>
<html n:if="!isset($parentModule) || substr($parentModule, 0, 21) === 'libchandler:absolute.'"> <html>
<head> <head>
<title> <title>
{ifset title}{include title} - {/ifset}{$instance_name} {ifset title}{include title} - {/ifset}{$instance_name}
@ -169,9 +169,9 @@
</a> </a>
<a href="/settings" class="link">{_my_settings}</a> <a href="/settings" class="link">{_my_settings}</a>
{var canAccessAdminPanel = $thisUser->getChandlerUser()->can("access")->model("admin")->whichBelongsTo(NULL)} {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 $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 $menuLinksAvaiable = sizeof(OPENVK_ROOT_CONF['openvk']['preferences']['menu']['links']) > 0 && $thisUser->getLeftMenuItemStatus('links')}
<div n:if="$canAccessAdminPanel || $canAccessHelpdesk || $menuLinksAvaiable" class="menu_divider"></div> <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="/admin" class="link" n:if="$canAccessAdminPanel" title="Админ-панель [Alt+Shift+A]" accesskey="a">Админ-панель</a>
<a href="/support/tickets" class="link" n:if="$canAccessHelpdesk">Helpdesk <a href="/support/tickets" class="link" n:if="$canAccessHelpdesk">Helpdesk
@ -191,6 +191,14 @@
<div n:if="$thisUser->getPinnedClubCount() > 0" class="menu_divider"></div> <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> <a n:foreach="$thisUser->getPinnedClubs() as $club" href="{$club->getURL()}" class="link group_link">{$club->getName()}</a>
</div> </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} &#xbb;</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']}" > <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;" /> <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> </a>
@ -256,7 +264,7 @@
</div> </div>
<div class="page_footer"> <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"> <div class="navigation_footer">
<a href="/about" class="link">{_footer_about_instance}</a> <a href="/about" class="link">{_footer_about_instance}</a>
@ -330,6 +338,7 @@
{/ifset} {/ifset}
</body> </body>
</html> </html>
{/if}
{if isset($parentModule) && substr($parentModule, 0, 21) !== 'libchandler:absolute.'} {if isset($parentModule) && substr($parentModule, 0, 21) !== 'libchandler:absolute.'}
<!-- INCLUDING TEMPLATE FROM PARENTMODULE: {$parentModule} --> <!-- INCLUDING TEMPLATE FROM PARENTMODULE: {$parentModule} -->

View file

@ -16,7 +16,7 @@
{include specpage, x => $dat} {include specpage, x => $dat}
{else} {else}
<div class="container_gray"> <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} {if sizeof($data) > 0}
<div class="content" n:foreach="$data as $dat"> <div class="content" n:foreach="$data as $dat">

View file

@ -9,7 +9,7 @@
<table width="100%" cellspacing="0" cellpadding="0"> <table width="100%" cellspacing="0" cellpadding="0">
<tbody> <tbody>
<tr valign="top"> <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> <h4>{_statistics}</h4>
<div style="margin-top: 5px;"> <div style="margin-top: 5px;">
{_on_this_instance_are} {_on_this_instance_are}
@ -21,6 +21,15 @@
<li><span>{tr("about_wall_posts", $postsCount)|noescape}</span></li> <li><span>{tr("about_wall_posts", $postsCount)|noescape}</span></li>
</ul> </ul>
</div> </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>
<td n:if="sizeof($admins) > 0"> <td n:if="sizeof($admins) > 0">
<h4>{_administrators}</h4> <h4>{_administrators}</h4>
@ -44,14 +53,23 @@
{if sizeof($popularClubs) !== 0} {if sizeof($popularClubs) !== 0}
<h4>{_most_popular_groups}</h4> <h4>{_most_popular_groups}</h4>
<ol> {var $entries = array_chunk($popularClubs, 10, true)}
<li n:foreach="$popularClubs as $entry" style="margin-top: 5px;"> <table width="100%" cellspacing="0" cellpadding="0">
<a href="{$entry->club->getURL()}">{$entry->club->getName()}</a> <tbody>
<div> <tr valign="top">
{tr("participants", $entry->subscriptions)} <td n:foreach="$entries as $chunk">
</div> <ol>
</li> <li value="{$num+1}" style="margin-top: 5px;" n:foreach="$chunk as $num => $club">
</ol> <a href="{$club->club->getURL()}">{$club->club->getName()}</a>
<div>
{tr("participants", $club->subscriptions)}
</div>
</li>
</ol>
</td>
</tr>
</tbody>
</table>
{/if} {/if}
<h4>{_rules}</h4> <h4>{_rules}</h4>

View file

@ -3,7 +3,7 @@
<head> <head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8" /> <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8" />
<style> <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} {str_replace("fonts/", "/assets/packages/static/openvk/js/node_modules/@atlassian/aui/dist/aui/fonts/", $css)|noescape}
</style> </style>
<title>{include title} - Админ-панель {=OPENVK_ROOT_CONF['openvk']['appearance']['name']}</title> <title>{include title} - Админ-панель {=OPENVK_ROOT_CONF['openvk']['appearance']['name']}</title>
@ -131,7 +131,7 @@
</div> </div>
<section class="aui-page-panel-content"> <section class="aui-page-panel-content">
{ifset $flashMessage} {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;"> <div class="aui-message aui-message-{$type}" style="margin-bottom: 15px;">
<p class="title"> <p class="title">
<strong>{$flashMessage->title}</strong> <strong>{$flashMessage->title}</strong>

View file

@ -11,9 +11,9 @@
{block content} {block content}
{var isMain = $mode === 'main'} {var $isMain = $mode === 'main'}
{var isBan = $mode === 'ban'} {var $isBan = $mode === 'ban'}
{var isFollowers = $mode === 'followers'} {var $isFollowers = $mode === 'followers'}
{if $isMain} {if $isMain}
@ -134,7 +134,7 @@
<!-- This followers block --> <!-- This followers block -->
{var followers = iterator_to_array($followers)} {var $followers = iterator_to_array($followers)}
<div class="aui-tabs horizontal-tabs"> <div class="aui-tabs horizontal-tabs">
<nav class="aui-navgroup aui-navgroup-horizontal"> <nav class="aui-navgroup aui-navgroup-horizontal">
@ -177,7 +177,7 @@
</tbody> </tbody>
</table> </table>
<div align="right"> <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}"> <a n:if="($_GET['p'] ?? 1) > 1" class="aui-button" href="?p={($_GET['p'] ?? 1) - 1}">
⭁ туда ⭁ туда

View file

@ -1,5 +1,5 @@
{extends "@layout.xml"} {extends "@layout.xml"}
{var search = true} {var $search = true}
{block title} {block title}
Группы Группы
@ -12,8 +12,8 @@
{block searchTitle}Поиск бутылок{/block} {block searchTitle}Поиск бутылок{/block}
{block content} {block content}
{var clubs = iterator_to_array($clubs)} {var $clubs = iterator_to_array($clubs)}
{var amount = sizeof($clubs)} {var $amount = sizeof($clubs)}
<table class="aui aui-table-list"> <table class="aui aui-table-list">
<thead> <thead>
@ -39,7 +39,7 @@
<a href="{$club->getURL()}">{$club->getCanonicalName()}</a> <a href="{$club->getURL()}">{$club->getCanonicalName()}</a>
</td> </td>
<td> <td>
{var user = $club->getOwner()} {var $user = $club->getOwner()}
<span class="aui-avatar aui-avatar-xsmall"> <span class="aui-avatar aui-avatar-xsmall">
<span class="aui-avatar-inner"> <span class="aui-avatar-inner">
@ -61,7 +61,7 @@
</table> </table>
<br/> <br/>
<div align="right"> <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}"> <a n:if="($_GET['p'] ?? 1) > 1" class="aui-button" href="?p={($_GET['p'] ?? 1) - 1}">
⭁ туда ⭁ туда

View file

@ -45,7 +45,7 @@
{/if} {/if}
<div align="right"> <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 n:if="($_GET['p'] ?? 1) > 1" class="aui-button" href="?act={$act}&p={($_GET['p'] ?? 1) - 1}">
⭁ туда ⭁ туда
</a> </a>

View file

@ -71,7 +71,7 @@
{/if} {/if}
<div align="right"> <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 n:if="($_GET['p'] ?? 1) > 1" class="aui-button" href="?p={($_GET['p'] ?? 1) - 1}">
⭁ туда ⭁ туда
</a> </a>

View file

@ -1,5 +1,5 @@
{extends "@layout.xml"} {extends "@layout.xml"}
{var search = true} {var $search = true}
{block title} {block title}
Пользователи Пользователи
@ -12,8 +12,8 @@
{block searchTitle}Поиск пиздюков{/block} {block searchTitle}Поиск пиздюков{/block}
{block content} {block content}
{var users = iterator_to_array($users)} {var $users = iterator_to_array($users)}
{var amount = sizeof($users)} {var $amount = sizeof($users)}
<table class="aui aui-table-list"> <table class="aui aui-table-list">
<thead> <thead>
@ -60,7 +60,7 @@
</table> </table>
<br/> <br/>
<div align="right"> <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}"> <a n:if="($_GET['p'] ?? 1) > 1" class="aui-button" href="?p={($_GET['p'] ?? 1) - 1}">
⭁ туда ⭁ туда

View file

@ -50,7 +50,7 @@
<br/> <br/>
<div align="right"> <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 n:if="($_GET['p'] ?? 1) > 1" class="aui-button" href="?p={($_GET['p'] ?? 1) - 1}">
⭁ туда ⭁ туда
</a> </a>

View file

@ -47,7 +47,7 @@
<span>{_"gender"}: </span> <span>{_"gender"}: </span>
</td> </td>
<td> <td>
{var femalePreferred = OPENVK_ROOT_CONF["openvk"]["preferences"]["femaleGenderPriority"]} {var $femalePreferred = OPENVK_ROOT_CONF["openvk"]["preferences"]["femaleGenderPriority"]}
<select name="sex" required> <select name="sex" required>
<option n:attr="selected => !$femalePreferred" value="male">{_"male"}</option> <option n:attr="selected => !$femalePreferred" value="male">{_"male"}</option>
<option n:attr="selected => $femalePreferred" value="female">{_"female"}</option> <option n:attr="selected => $femalePreferred" value="female">{_"female"}</option>

View file

@ -92,7 +92,7 @@
<span class="nobold">{_group_administrators_list}: </span> <span class="nobold">{_group_administrators_list}: </span>
</td> </td>
<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="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="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> <input type="radio" name="administrators_list_display" value="2" n:attr="checked => $club->getAdministratorsListDisplay() == 2" /> {_group_dont_display_administrators_list}<br>

View file

@ -1,9 +1,9 @@
{extends "../@listView.xml"} {extends "../@listView.xml"}
{var $Manager = openvk\Web\Models\Entities\Manager::class} {var $Manager = openvk\Web\Models\Entities\Manager::class}
{var iterator = $onlyShowManagers ? $managers : $followers} {var $iterator = $onlyShowManagers ? $managers : $followers}
{var count = $paginatorConf->count} {var $count = $paginatorConf->count}
{var page = $paginatorConf->page} {var $page = $paginatorConf->page}
{var perPage = 6} {var $perPage = 6}
{block title}{_followers} {$club->getCanonicalName()}{/block} {block title}{_followers} {$club->getCanonicalName()}{/block}
@ -49,8 +49,8 @@
{/block} {/block}
{block description} {block description}
{var user = $x instanceof $Manager ? $x->getUser() : $x} {var $user = $x instanceof $Manager ? $x->getUser() : $x}
{var manager = $x instanceof $Manager ? $x : $club->getManager($user, !$club->canBeModifiedBy($thisUser))} {var $manager = $x instanceof $Manager ? $x : $club->getManager($user, !$club->canBeModifiedBy($thisUser))}
<table> <table>
<tbody> <tbody>
<tr> <tr>
@ -106,8 +106,8 @@
{/block} {/block}
{block actions} {block actions}
{var user = $x instanceof $Manager ? $x->getUser() : $x} {var $user = $x instanceof $Manager ? $x->getUser() : $x}
{var manager = $x instanceof $Manager ? $x : $club->getManager($user, !$club->canBeModifiedBy($thisUser))} {var $manager = $x instanceof $Manager ? $x : $club->getManager($user, !$club->canBeModifiedBy($thisUser))}
{if $club->canBeModifiedBy($thisUser ?? NULL)} {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()"> <a class="profile_link" href="/club{$club->getId()}/setAdmin?user={$user->getId()}&hash={rawurlencode($csrfToken)}" n:if="$club->getOwner()->getId() !== $user->getId()">
{if $manager} {if $manager}

View file

@ -14,6 +14,8 @@
{block content} {block content}
<div class="left_big_block"> <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);"> <div class="content_title_expanded" onclick="hidePanel(this);">
{_"information"} {_"information"}
</div> </div>
@ -41,7 +43,7 @@
</table> </table>
</div> </div>
<div n:if="$club->getFollowersCount() > 0"> <div n:if="$club->getFollowersCount() > 0">
{var followersCount = $club->getFollowersCount()} {var $followersCount = $club->getFollowersCount()}
<div class="content_title_expanded" onclick="hidePanel(this, {$followersCount});"> <div class="content_title_expanded" onclick="hidePanel(this, {$followersCount});">
{_participants} {_participants}
@ -91,8 +93,8 @@
{presenter "openvk!Wall->wallEmbedded", -$club->getId()} {presenter "openvk!Wall->wallEmbedded", -$club->getId()}
</div> </div>
<div class="right_small_block"> <div class="right_small_block">
{var avatarPhoto = $club->getAvatarPhoto()} {var $avatarPhoto = $club->getAvatarPhoto()}
{var avatarLink = ((is_null($avatarPhoto) ? FALSE : $avatarPhoto->isAnonymous()) ? "/photo" . ("s/" . base_convert((string) $avatarPhoto->getId(), 10, 32)) : $club->getAvatarLink())} {var $avatarLink = ((is_null($avatarPhoto) ? FALSE : $avatarPhoto->isAnonymous()) ? "/photo" . ("s/" . base_convert((string) $avatarPhoto->getId(), 10, 32)) : $club->getAvatarLink())}
<a href="{$avatarLink|nocheck}"> <a href="{$avatarLink|nocheck}">
<img src="{$club->getAvatarUrl('normal')}" style="width: 100%; image-rendering: -webkit-optimize-contrast;" /> <img src="{$club->getAvatarUrl('normal')}" style="width: 100%; image-rendering: -webkit-optimize-contrast;" />
</a> </a>
@ -132,7 +134,7 @@
{_"creator"} {_"creator"}
</div> </div>
<div class="avatar-list-item" style="padding: 8px;"> <div class="avatar-list-item" style="padding: 8px;">
{var author = $club->getOwner()} {var $author = $club->getOwner()}
<div class="avatar"> <div class="avatar">
<a href="{$author->getURL()}"> <a href="{$author->getURL()}">
<img class="ava" src="{$author->getAvatarUrl()}" /> <img class="ava" src="{$author->getAvatarUrl()}" />
@ -149,7 +151,7 @@
</div> </div>
</div> </div>
<div n:if="$club->getAdministratorsListDisplay() == 1"> <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});"> <div class="content_title_expanded" onclick="hidePanel(this, {$managersCount});">
{_"administrators"} {_"administrators"}
@ -163,7 +165,7 @@
</div> </div>
<div class="avatar-list"> <div class="avatar-list">
<div class="avatar-list-item" n:if="!$club->isOwnerHidden()"> <div class="avatar-list-item" n:if="!$club->isOwnerHidden()">
{var author = $club->getOwner()} {var $author = $club->getOwner()}
<div class="avatar"> <div class="avatar">
<a href="{$author->getURL()}"> <a href="{$author->getURL()}">
<img class="ava" src="{$author->getAvatarUrl()}" /> <img class="ava" src="{$author->getAvatarUrl()}" />
@ -175,7 +177,7 @@
</div> </div>
</div> </div>
<div class="avatar-list-item" n:foreach="$club->getManagers(1, true) as $manager"> <div class="avatar-list-item" n:foreach="$club->getManagers(1, true) as $manager">
{var user = $manager->getUser()} {var $user = $manager->getUser()}
<div class="avatar"> <div class="avatar">
<a href="{$user->getURL()}"> <a href="{$user->getURL()}">
<img height="32" class="ava" src="{$user->getAvatarUrl()}" /> <img height="32" class="ava" src="{$user->getAvatarUrl()}" />
@ -203,7 +205,7 @@
<div style="padding: 5px;"> <div style="padding: 5px;">
<div class="ovk-album" style="display: inline-block;" n:foreach="$albums as $album"> <div class="ovk-album" style="display: inline-block;" n:foreach="$albums as $album">
<div style="text-align: center;float: left;height: 54pt;width: 100px;"> <div style="text-align: center;float: left;height: 54pt;width: 100px;">
{var cover = $album->getCoverPhoto()} {var $cover = $album->getCoverPhoto()}
<img <img
src="{is_null($cover)?'/assets/packages/static/openvk/img/camera_200.png':$cover->getURL()}" src="{is_null($cover)?'/assets/packages/static/openvk/img/camera_200.png':$cover->getURL()}"

View file

@ -6,7 +6,7 @@
<a href="/im">{_my_messages}</a> » <a href="/im">{_my_messages}</a> »
<a href="{$correspondent->getURL()}">{$correspondent->getCanonicalName()}</a> <a href="{$correspondent->getURL()}">{$correspondent->getCanonicalName()}</a>
<div n:if="($online = $correspondent->getOnline()->timestamp()) + 2505600 > time()" style="float: right;"> <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} {if 5 >= $diff->i}
<span><b>{_online}</b></span> <span><b>{_online}</b></span>
{else} {else}

View file

@ -21,8 +21,8 @@
<div n:foreach="$corresps as $coresp" <div n:foreach="$corresps as $coresp"
class="crp-entry" class="crp-entry"
onmousedown="window.location.href = {$coresp->getURL()};" > onmousedown="window.location.href = {$coresp->getURL()};" >
{var recipient = $coresp->getCorrespondents()[1]} {var $recipient = $coresp->getCorrespondents()[1]}
{var lastMsg = $coresp->getPreviewMessage()} {var $lastMsg = $coresp->getPreviewMessage()}
<div class="crp-entry--image"> <div class="crp-entry--image">
<img src="{$recipient->getAvatarURL('miniscule')}" <img src="{$recipient->getAvatarURL('miniscule')}"
@ -33,7 +33,7 @@
<span>{$lastMsg->getSendTime()->format("%e %B %G" . tr("time_at_sp") . "%X")}</span> <span>{$lastMsg->getSendTime()->format("%e %B %G" . tr("time_at_sp") . "%X")}</span>
</div> </div>
<div n:class="crp-entry--message, $lastMsg->getUnreadState() ? unread"> <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()"> <div class="crp-entry--message---av" n:if="$_author->getId() === $thisUser->getId()">
<img src="{$_author->getAvatarURL('miniscule')}" <img src="{$_author->getAvatarURL('miniscule')}"

View file

@ -3,7 +3,7 @@
{block title}{_edit_note}{/block} {block title}{_edit_note}{/block}
{block header} {block header}
{var author = $note->getOwner()} {var $author = $note->getOwner()}
<a href="{$author->getURL()}">{$author->getCanonicalName()}</a> <a href="{$author->getURL()}">{$author->getCanonicalName()}</a>
» »
<a href="/notes{$author->getId()}">{_notes}</a> <a href="/notes{$author->getId()}">{_notes}</a>

View file

@ -1,6 +1,6 @@
{extends "../@listView.xml"} {extends "../@listView.xml"}
{var iterator = iterator_to_array($notes)} {var $iterator = iterator_to_array($notes)}
{var page = $paginatorConf->page} {var $page = $paginatorConf->page}
{block title}{_notes}{/block} {block title}{_notes}{/block}
@ -62,7 +62,7 @@
<div class="container_gray" style="background: white; border-top: none;"> <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} {if sizeof($data) > 0}
<div n:foreach="$data as $dat"> <div n:foreach="$data as $dat">

View file

@ -3,7 +3,7 @@
{block title}{$note->getName()}{/block} {block title}{$note->getName()}{/block}
{block header} {block header}
{var author = $note->getOwner()} {var $author = $note->getOwner()}
<a href="{$author->getURL()}">{$author->getCanonicalName()}</a> <a href="{$author->getURL()}">{$author->getCanonicalName()}</a>
» »
<a href="/notes{$author->getId()}">{_notes}</a> <a href="/notes{$author->getId()}">{_notes}</a>
@ -12,7 +12,7 @@
{/block} {/block}
{block content} {block content}
{var author = $note->getOwner()} {var $author = $note->getOwner()}
<style> <style>
#userContent img { #userContent img {
max-width: 245pt; max-width: 245pt;

View file

@ -1,5 +1,5 @@
{extends "../@listView.xml"} {extends "../@listView.xml"}
{var sorting = false} {var $sorting = false}
{block title} {block title}
{_feedback} {_feedback}

View file

@ -3,7 +3,7 @@
{block title}Альбом {$album->getName()}{/block} {block title}Альбом {$album->getName()}{/block}
{block header} {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()}"> <a href="{$album->getOwner()->getURL()}">
{$album->getOwner()->getCanonicalName()} {$album->getOwner()->getCanonicalName()}

View file

@ -1,6 +1,6 @@
{extends "../@listView.xml"} {extends "../@listView.xml"}
{var iterator = iterator_to_array($albums)} {var $iterator = iterator_to_array($albums)}
{var page = $paginatorConf->page} {var $page = $paginatorConf->page}
{block title}{_"albums"} {$owner->getCanonicalName()}{/block} {block title}{_"albums"} {$owner->getCanonicalName()}{/block}
@ -26,7 +26,7 @@
<span n:if="$canEdit" style="float: right;"> <span n:if="$canEdit" style="float: right;">
&nbsp;|&nbsp; &nbsp;|&nbsp;
{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> <a href="/albums/create{$isClub ? '?gpid=' . $owner->getId() : ''}">{_create_album}</a>
</span> </span>
</div> </div>
@ -44,8 +44,8 @@
{/block} {/block}
{block preview} {block preview}
{var cover = $x->getCoverPhoto()} {var $cover = $x->getCoverPhoto()}
{var preview = is_null($cover) ? "/assets/packages/static/openvk/img/camera_200.png" : $cover->getURLBySizeId("normal")} {var $preview = is_null($cover) ? "/assets/packages/static/openvk/img/camera_200.png" : $cover->getURLBySizeId("normal")}
<a href="/album{$x->getPrettyId()}"> <a href="/album{$x->getPrettyId()}">
<img src="{$preview}" alt="{$x->getName()}" style="height: 130px; width: 170px; object-fit: cover" /> <img src="{$preview}" alt="{$x->getName()}" style="height: 130px; width: 170px; object-fit: cover" />

View file

@ -70,7 +70,7 @@
{if $thisUser->getChandlerUser()->can("write")->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)} {if $thisUser->getChandlerUser()->can("write")->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)}
<a href="{$comment->getUser()->getURL()}"> <a href="{$comment->getUser()->getURL()}">
<span class="nobold"> <span class="nobold">
{var lastName = $comment->getUser()->getLastName()} {var $lastName = $comment->getUser()->getLastName()}
{if empty(trim($lastName))} {if empty(trim($lastName))}
({$comment->getUser()->getFirstName()}) ({$comment->getUser()->getFirstName()})
{else} {else}

View file

@ -6,9 +6,9 @@
{/block} {/block}
{block content} {block content}
{var isMain = $mode === 'faq'} {var $isMain = $mode === 'faq'}
{var isNew = $mode === 'new'} {var $isNew = $mode === 'new'}
{var isList = $mode === 'list'} {var $isList = $mode === 'list'}
{if $thisUser} {if $thisUser}
<div class="tabs"> <div class="tabs">

View file

@ -37,7 +37,7 @@
{/block} {/block}
{block description} {block description}
{var author = $x->getUser()} {var $author = $x->getUser()}
{ovk_proc_strtr($x->getContext(), 50)}<br/> {ovk_proc_strtr($x->getContext(), 50)}<br/>
<span class="nobold">{_author}: </span> <a href="{$author->getURL()}">{$author->getCanonicalName()}</a> <span class="nobold">{_author}: </span> <a href="{$author->getURL()}">{$author->getCanonicalName()}</a>

View file

@ -109,7 +109,7 @@
{if $comment->getUType() === 1} {if $comment->getUType() === 1}
<div class="post-menu"> <div class="post-menu">
{var isLikedByUser = $comment->isLikedByUser()} {var $isLikedByUser = $comment->isLikedByUser()}
<strong id="markText-{$comment->getId()}"> <strong id="markText-{$comment->getId()}">
{if !is_null($isLikedByUser)} {if !is_null($isLikedByUser)}
{if $comment->isLikedByUser()} {if $comment->isLikedByUser()}

View file

@ -1,6 +1,6 @@
{extends "../@listView.xml"} {extends "../@listView.xml"}
{var iterator = iterator_to_array($topics)} {var $iterator = iterator_to_array($topics)}
{var page = $paginatorConf->page} {var $page = $paginatorConf->page}
{block title}{_discussions} {$club->getCanonicalName()}{/block} {block title}{_discussions} {$club->getCanonicalName()}{/block}
@ -46,7 +46,7 @@
<div style="float: left;"> <div style="float: left;">
{tr("messages", $x->getCommentsCount())} {tr("messages", $x->getCommentsCount())}
</div> </div>
{var lastComment = $x->getLastComment()} {var $lastComment = $x->getLastComment()}
<div n:if="$lastComment" class="avatar-list-item" style="float: right;"> <div n:if="$lastComment" class="avatar-list-item" style="float: right;">
<div class="avatar"> <div class="avatar">
<a href="{$lastComment->getOwner()->getURL()}"> <a href="{$lastComment->getOwner()->getURL()}">

View file

@ -7,10 +7,10 @@
{block content} {block content}
{var isMain = $mode === 'main'} {var $isMain = $mode === 'main'}
{var isContacts = $mode === 'contacts'} {var $isContacts = $mode === 'contacts'}
{var isInterests = $mode === 'interests'} {var $isInterests = $mode === 'interests'}
{var isAvatar = $mode === 'avatar'} {var $isAvatar = $mode === 'avatar'}
<div n:if="$user->hasPendingNumberChange()" class="msg"> <div n:if="$user->hasPendingNumberChange()" class="msg">
<b>Подтверждение номера телефона</b><br/> <b>Подтверждение номера телефона</b><br/>
Введите код для подтверждения смены номера: <a href="/edit/verify_phone">ввести код</a>. Введите код для подтверждения смены номера: <a href="/edit/verify_phone">ввести код</a>.

View file

@ -1,17 +1,17 @@
{extends "../@listView.xml"} {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"} {if $act == "incoming"}
{var iterator = iterator_to_array($user->getFollowers($page))} {var $iterator = iterator_to_array($user->getFollowers($page))}
{var count = $user->getFollowersCount()} {var $count = $user->getFollowersCount()}
{elseif $act == "outcoming"} {elseif $act == "outcoming"}
{var iterator = iterator_to_array($user->getSubscriptions($page))} {var $iterator = iterator_to_array($user->getSubscriptions($page))}
{var count = $user->getSubscriptionsCount()} {var $count = $user->getSubscriptionsCount()}
{else} {else}
{var iterator = iterator_to_array($user->getFriends($page))} {var $iterator = iterator_to_array($user->getFriends($page))}
{var count = $user->getFriendsCount()} {var $count = $user->getFriendsCount()}
{/if} {/if}
{block title} {block title}
@ -113,7 +113,7 @@
{block actions} {block actions}
{if $x->getId() !== $thisUser->getId()} {if $x->getId() !== $thisUser->getId()}
{var subStatus = $x->getSubscriptionStatus($thisUser)} {var $subStatus = $x->getSubscriptionStatus($thisUser)}
{if $subStatus === 0} {if $subStatus === 0}
<form action="/setSub/user" method="post" class="profile_link_form"> <form action="/setSub/user" method="post" class="profile_link_form">
<input type="hidden" name="act" value="add" /> <input type="hidden" name="act" value="add" />

View file

@ -1,6 +1,6 @@
{extends "../@listView.xml"} {extends "../@listView.xml"}
{var iterator = $user->getClubs($page, $admin)} {var $iterator = $user->getClubs($page, $admin)}
{var count = $user->getClubCount($admin)} {var $count = $user->getClubCount($admin)}
{block title} {block title}
{_groups} {_groups}
@ -73,7 +73,7 @@
{/block} {/block}
{block actions} {block actions}
{var clubPinned = $thisUser->isClubPinned($x)} {var $clubPinned = $thisUser->isClubPinned($x)}
{if $x->canBeModifiedBy($thisUser ?? NULL)} {if $x->canBeModifiedBy($thisUser ?? NULL)}
<div class="navigation" style="width: 140px;"> <div class="navigation" style="width: 140px;">
<a class="link" href="{$x->getURL()}"> <a class="link" href="{$x->getURL()}">

View file

@ -7,11 +7,11 @@
{block content} {block content}
{var isMain = $mode === 'main'} {var $isMain = $mode === 'main'}
{var isPrivacy = $mode === 'privacy'} {var $isPrivacy = $mode === 'privacy'}
{var isFinance = $mode === 'finance'} {var $isFinance = $mode === 'finance'}
{var isFinanceTU = $mode === 'finance.top-up'} {var $isFinanceTU = $mode === 'finance.top-up'}
{var isInterface = $mode === 'interface'} {var $isInterface = $mode === 'interface'}
<div class="tabs"> <div class="tabs">
<div n:attr="id => ($isMain ? 'activetabs' : 'ki')" class="tab"> <div n:attr="id => ($isMain ? 'activetabs' : 'ki')" class="tab">

View file

@ -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="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> <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} {if $subStatus === 0}
<form action="/setSub/user" method="post" class="profile_link_form"> <form action="/setSub/user" method="post" class="profile_link_form">
<input type="hidden" name="act" value="add" /> <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> <a n:if="$user->getFollowersCount() > 0" href="/friends{$user->getId()}?act=incoming" class="profile_link">{tr("followers", $user->getFollowersCount())}</a>
</div> </div>
<div n:if="isset($thisUser) && !$thisUser->prefersNotToSeeRating()" class="profile-hints"> <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 n:class="completeness-gauge, $completeness->total >= 100 ? completeness-gauge-gold">
<div style="width: {$completeness->percent}%"></div> <div style="width: {$completeness->percent}%"></div>
@ -174,7 +174,7 @@
</div> </div>
<br /> <br />
<div n:if="$user->getFriendsCount() > 0 && $user->getPrivacyPermission('friends.read', $thisUser ?? NULL)"> <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});"> <div class="content_title_expanded" onclick="hidePanel(this, {$friendCount});">
{_"friends"} {_"friends"}
@ -215,7 +215,7 @@
<div style="padding: 5px;"> <div style="padding: 5px;">
<div class="ovk-album" style="display: inline-block;" n:foreach="$albums as $album"> <div class="ovk-album" style="display: inline-block;" n:foreach="$albums as $album">
<div style="text-align: center;float: left;height: 54pt;width: 100px;"> <div style="text-align: center;float: left;height: 54pt;width: 100px;">
{var cover = $album->getCoverPhoto()} {var $cover = $album->getCoverPhoto()}
<img <img
src="{is_null($cover)?'/assets/packages/static/openvk/img/camera_200.png':$cover->getURLBySizeId('small')}" src="{is_null($cover)?'/assets/packages/static/openvk/img/camera_200.png':$cover->getURLBySizeId('small')}"
@ -284,7 +284,7 @@
</div> </div>
</div> </div>
<div n:if="$user->getClubCount() > 0 && $user->getPrivacyPermission('groups.read', $thisUser ?? NULL)"> <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})"> <div class="content_title_expanded" onclick="hidePanel(this, {$clubsCount})">
{_"groups"} {_"groups"}
</div> </div>
@ -303,7 +303,7 @@
</div> </div>
</div> </div>
<div n:if="$user->getMeetingCount() > 0 && $user->getPrivacyPermission('groups.read', $thisUser ?? NULL)"> <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})"> <div class="content_title_expanded" onclick="hidePanel(this, {$meetingCount})">
{_meetings} {_meetings}
</div> </div>
@ -327,7 +327,7 @@
<div class="right_big_block"> <div class="right_big_block">
<div class="page_info"> <div class="page_info">
<div n:if="!is_null($alert = $user->getAlert())" class="user-alert">{strpos($alert, "@") === 0 ? tr(substr($alert, 1)) : $alert}</div> <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;"> <div n:if="$thatIsThisUser" class="page_status_popup" id="status_editor" style="display: none;">
<form name="status_popup_form" onsubmit="changeStatus(); return false;"> <form name="status_popup_form" onsubmit="changeStatus(); return false;">
<div style="margin-bottom: 10px;"> <div style="margin-bottom: 10px;">
@ -495,7 +495,7 @@
</div> </div>
<div class="content_list long"> <div class="content_list long">
<div class="cl_element" style="width: 25%;" n:foreach="$user->getGifts(1, 4) as $giftDescriptor"> <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"> <div class="cl_avatar">
<a href="{$hideInfo ? 'javascript:false' : $giftDescriptor->sender->getURL()}"> <a href="{$hideInfo ? 'javascript:false' : $giftDescriptor->sender->getURL()}">
<img style="width: 70px; max-height: 70px;" <img style="width: 70px; max-height: 70px;"

View file

@ -4,82 +4,86 @@
{tr("user_banned", htmlentities($user->getFirstName()))|noescape}<br/> {tr("user_banned", htmlentities($user->getFirstName()))|noescape}<br/>
{_"user_banned_comment"} <b>{$user->getBanReason()}</b>. {_"user_banned_comment"} <b>{$user->getBanReason()}</b>.
</p> </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)"> {if isset($thisUser)}
<br /> <p n:if="$thisUser->getChandlerUser()->can('access')->model('admin')->whichBelongsTo(NULL) || $thisUser->getChandlerUser()->can('write')->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)">
<a n:if="$thisUser->getChandlerUser()->can('access')->model('admin')->whichBelongsTo(NULL)" href="javascript:unbanUser()" class="button">{_unban_user_action}</a> <br />
<a n:if="$thisUser->getChandlerUser()->can('write')->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)" href="javascript:toggleBanInSupport()" class="button"> <a n:if="$thisUser->getChandlerUser()->can('access')->model('admin')->whichBelongsTo(NULL)" href="javascript:unbanUser()" class="button">{_unban_user_action}</a>
{if $user->isBannedInSupport()} <a n:if="$thisUser->getChandlerUser()->can('write')->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)" href="javascript:toggleBanInSupport()" class="button">
{_unban_in_support_user_action} {if $user->isBannedInSupport()}
{else} {_unban_in_support_user_action}
{_ban_in_support_user_action} {else}
{/if} {_ban_in_support_user_action}
</a> {/if}
</p> </a>
</p>
{/if}
</center> </center>
<script n:if="isset($thisUser) && $thisUser->getChandlerUser()->can('access')->model('admin')->whichBelongsTo(NULL)"> {if isset($thisUser)}
function unbanUser() { <script n:if="$thisUser->getChandlerUser()->can('access')->model('admin')->whichBelongsTo(NULL)">
uUnbanMsgTxt = "Вы собираетесь разбанить пользователя " + {$user->getCanonicalName()} + "."; function unbanUser() {
uUnbanMsgTxt += "<br/>Сейчас он заблокирован по причине: <strong>" + {$user->getBanReason()} + "</strong>."; uUnbanMsgTxt = "Вы собираетесь разбанить пользователя " + {$user->getCanonicalName()} + ".";
uUnbanMsgTxt += "<br/>Сейчас он заблокирован по причине: <strong>" + {$user->getBanReason()} + "</strong>.";
MessageBox("Разбанить " + {$user->getFirstName()}, uUnbanMsgTxt, ["Подтвердить", "Отмена"], [ 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, ["Подтвердить", "Отмена"], [
(function() { (function() {
xhr = new XMLHttpRequest(); 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() { xhr.onload = (function() {
if(xhr.responseText.indexOf("success") === -1) if(xhr.responseText.indexOf("success") === -1)
MessageBox("Ошибка", "Не удалось разблокировать пользователя в поддержке...", ["OK"], [Function.noop]); MessageBox("Ошибка", "Не удалось разблокировать пользователя...", ["OK"], [Function.noop]);
else else
MessageBox("Операция успешна", "Пользователь разблокирован в поддержке", ["OK"], [Function.noop]); MessageBox("Операция успешна", "Пользователь разблокирован", ["OK"], [Function.noop]);
}); });
xhr.send(null); xhr.send(null);
}), }),
Function.noop Function.noop
]); ]);
} }
{else} </script>
function toggleBanInSupport() {
uBanMsgTxt = "Вы собираетесь заблокировать в поддержке пользователя " + {$user->getCanonicalName()} + ".";
uBanMsgTxt += "<br/><br/><b>Причина бана</b>: <input type='text' id='uBanMsgInput' placeholder='придумайте что-нибудь крутое' />";
MessageBox("Заблокировать в поддержке " + {$user->getFirstName()}, uBanMsgTxt, ["Подтвердить", "Отмена"], [ <script n:if="$thisUser->getChandlerUser()->can('write')->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)">
(function() { {if $user->isBannedInSupport()}
res = document.querySelector("#uBanMsgInput").value; function toggleBanInSupport() {
xhr = new XMLHttpRequest(); uBanMsgTxt = "Вы собираетесь разблокировать в поддержке пользователя " + {$user->getCanonicalName()} + ".";
xhr.open("GET", "/admin/support/ban/" + {$user->getId()} + "?reason=" + res + "&hash=" + {rawurlencode($csrfToken)}, true); uBanMsgTxt += "<br/>Сейчас он заблокирован по причине <strong>" + {$user->getBanInSupportReason()} + "</strong>.";
xhr.onload = (function() {
if(xhr.responseText.indexOf("success") === -1) MessageBox("Разблокировать в поддержке " + {$user->getFirstName()}, uBanMsgTxt, ["Подтвердить", "Отмена"], [
MessageBox("Ошибка", "Не удалось заблокировать пользователя в поддержке...", ["OK"], [Function.noop]); (function() {
else xhr = new XMLHttpRequest();
MessageBox("Операция успешна", "Пользователь заблокирован в поддержке", ["OK"], [Function.noop]); xhr.open("GET", "/admin/support/unban/" + {$user->getId()} + "?hash=" + {rawurlencode($csrfToken)}, true);
}); xhr.onload = (function() {
xhr.send(null); if(xhr.responseText.indexOf("success") === -1)
}), MessageBox("Ошибка", "Не удалось разблокировать пользователя в поддержке...", ["OK"], [Function.noop]);
Function.noop else
]); MessageBox("Операция успешна", "Пользователь разблокирован в поддержке", ["OK"], [Function.noop]);
} });
{/if} xhr.send(null);
</script> }),
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}

View file

@ -1,7 +1,7 @@
{extends "../@listView.xml"} {extends "../@listView.xml"}
{var iterator = $videos} {var $iterator = $videos}
{var count = $paginatorConf->count} {var $count = $paginatorConf->count}
{var page = $paginatorConf->page} {var $page = $paginatorConf->page}
{block title}{_"videos"} {$user->getCanonicalName()}{/block} {block title}{_"videos"} {$user->getCanonicalName()}{/block}

View file

@ -15,7 +15,7 @@
{if $video->getType() === 0} {if $video->getType() === 0}
<video width="610" src="{$video->getURL()}" controls></video> <video width="610" src="{$video->getURL()}" controls></video>
{else} {else}
{var driver = $video->getVideoDriver()} {var $driver = $video->getVideoDriver()}
{if !$driver} {if !$driver}
Эта видеозапись не поддерживается в вашей версии OpenVK. Эта видеозапись не поддерживается в вашей версии OpenVK.
{else} {else}

View file

@ -27,9 +27,9 @@
<div style="float: left; min-height: 100px; width: 32%;"> <div style="float: left; min-height: 100px; width: 32%;">
<h4>{_actions}</h4> <h4>{_actions}</h4>
{if isset($thisUser)} {if isset($thisUser)}
{var canDelete = $post->canBeDeletedBy($thisUser)} {var $canDelete = $post->canBeDeletedBy($thisUser)}
{if $thisUser->getId() != $post->getOwner()->getId()} {if $thisUser->getId() != $post->getOwner()->getId()}
{var canReport = true} {var $canReport = true}
{/if} {/if}
{/if} {/if}

View file

@ -1,6 +1,6 @@
{if $attachment instanceof \openvk\Web\Models\Entities\Photo} {if $attachment instanceof \openvk\Web\Models\Entities\Photo}
{if !$attachment->isDeleted()} {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}"> <a href="{$link}">
<img class="media" src="{$attachment->getURLBySizeId('normal')}" alt="{$attachment->getDescription()}" /> <img class="media" src="{$attachment->getURLBySizeId('normal')}" alt="{$attachment->getDescription()}" />
</a> </a>

View file

@ -1,6 +1,6 @@
{var author = $comment->getOwner()} {var $author = $comment->getOwner()}
{var $Club = openvk\Web\Models\Entities\Club::class} {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> <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"> <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">

View file

@ -1,8 +1,8 @@
<h4 n:if="$showTitle ?? true">{_comments} ({$count})</h4> <h4 n:if="$showTitle ?? true">{_comments} ({$count})</h4>
<div n:ifset="$thisUser"> <div n:ifset="$thisUser">
{var commentsURL = "/al_comments/create/$model/" . $parent->getId()} {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 $club = $parent instanceof \openvk\Web\Models\Entities\Post && $parent->getTargetWall() < 0 ? (new openvk\Web\Models\Repositories\Clubs)->get(abs($parent->getTargetWall())) : $club}
{if !$readOnly} {if !$readOnly}
{include "textArea.xml", route => $commentsURL, postOpts => false, graffiti => (bool) ovkGetQuirk("comments.allow-graffiti"), club => $club} {include "textArea.xml", route => $commentsURL, postOpts => false, graffiti => (bool) ovkGetQuirk("comments.allow-graffiti"), club => $club}
{/if} {/if}
@ -16,17 +16,6 @@
{include "paginator.xml", conf => (object) ["page" => $page, "count" => $count, "amount" => sizeof($comments), "perPage" => 10]} {include "paginator.xml", conf => (object) ["page" => $page, "count" => $count, "amount" => sizeof($comments), "perPage" => 10]}
</div> </div>
{else} {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} {_comments_tip}
{/if} {/if}

View file

@ -1,5 +1,5 @@
{var post = $notification->getModel(0)} {var $post = $notification->getModel(0)}
{var user = $notification->getModel(1)} {var $user = $notification->getModel(1)}
<a href="{$user->getURL()}"><b>{$user->getCanonicalName()}</b></a> <a href="{$user->getURL()}"><b>{$user->getCanonicalName()}</b></a>
{$notification->getDateTime()} {_nt_liked_yours} {$notification->getDateTime()} {_nt_liked_yours}

View file

@ -1,5 +1,5 @@
{var post = $notification->getModel(0)} {var $post = $notification->getModel(0)}
{var user = $notification->getModel(1)} {var $user = $notification->getModel(1)}
<a href="{$user->getURL()}"><b>{$user->getCanonicalName()}</b></a> <a href="{$user->getURL()}"><b>{$user->getCanonicalName()}</b></a>
{$notification->getDateTime()} {_nt_shared_yours} {$notification->getDateTime()} {_nt_shared_yours}

View file

@ -1,4 +1,4 @@
{var user = $notification->getModel(1)} {var $user = $notification->getModel(1)}
<a href="{$user->getURL()}"><b>{$user->getCanonicalName()}</b></a> <a href="{$user->getURL()}"><b>{$user->getCanonicalName()}</b></a>
{$notification->getDateTime()} {_nt_commented_yours} {include under}: "{$notification->getData()}". {$notification->getDateTime()} {_nt_commented_yours} {include under}: "{$notification->getData()}".

View file

@ -1,5 +1,5 @@
{extends "@default.xml"} {extends "@default.xml"}
{var post = $notification->getModel(0)} {var $post = $notification->getModel(0)}
{block under} {block under}
{_nt_yours_feminitive_adjective} <a href="/note{$post->getPrettyId()}">{_nt_note_instrumental}</a> {_nt_yours_feminitive_adjective} <a href="/note{$post->getPrettyId()}">{_nt_note_instrumental}</a>

View file

@ -1,5 +1,5 @@
{extends "@default.xml"} {extends "@default.xml"}
{var post = $notification->getModel(0)} {var $post = $notification->getModel(0)}
{block under} {block under}
{_nt_yours_feminitive_adjective} <a href="/photo{$post->getPrettyId()}">{_nt_photo_instrumental}</a> {_nt_yours_feminitive_adjective} <a href="/photo{$post->getPrettyId()}">{_nt_photo_instrumental}</a>

View file

@ -1,5 +1,5 @@
{extends "@default.xml"} {extends "@default.xml"}
{var post = $notification->getModel(0)} {var $post = $notification->getModel(0)}
{block under} {block under}
{_nt_yours_adjective} <a href="/wall{$post->getPrettyId()}">{_nt_post_instrumental}</a> {_nt_from} {$post->getPublicationTime()} {_nt_yours_adjective} <a href="/wall{$post->getPrettyId()}">{_nt_post_instrumental}</a> {_nt_from} {$post->getPublicationTime()}

View file

@ -1,5 +1,5 @@
{extends "@default.xml"} {extends "@default.xml"}
{var post = $notification->getModel(0)} {var $post = $notification->getModel(0)}
{block under} {block under}
{_nt_yours_adjective} <a href="/video{$post->getPrettyId()}">{_video}</a> {_nt_yours_adjective} <a href="/video{$post->getPrettyId()}">{_video}</a>

View file

@ -1,5 +1,5 @@
{extends "@default.xml"} {extends "@default.xml"}
{var post = $notification->getModel(0)} {var $post = $notification->getModel(0)}
{block under} {block under}
{_nt_yours_adjective} <a href="/topic{$post->getPrettyId()}">{_nt_topic_instrumental}</a> {_nt_yours_adjective} <a href="/topic{$post->getPrettyId()}">{_nt_topic_instrumental}</a>

View file

@ -1,5 +1,5 @@
{var post = $notification->getModel(0)} {var $post = $notification->getModel(0)}
{var user = $notification->getModel(1)} {var $user = $notification->getModel(1)}
<a href="{$user->getURL()}"><b>{$user->getCanonicalName()}</b></a> <a href="{$user->getURL()}"><b>{$user->getCanonicalName()}</b></a>
{$notification->getDateTime()} {_nt_written_on_your_wall} {$notification->getDateTime()} {_nt_written_on_your_wall}

View file

@ -1,5 +1,5 @@
{var club = $notification->getModel(0)} {var $club = $notification->getModel(0)}
{var user = $notification->getModel(1)} {var $user = $notification->getModel(1)}
<a href="{$user->getURL()}"><b>{$user->getCanonicalName()}</b></a> <a href="{$user->getURL()}"><b>{$user->getCanonicalName()}</b></a>
{_nt_made_you_admin} {_nt_made_you_admin}

View file

@ -1,4 +1,4 @@
{var gift = $notification->getModel(0)} {var $gift = $notification->getModel(0)}
{var sender = $notification->getModel(1)} {var $sender = $notification->getModel(1)}
<a href="{$sender->getURL()}"><b>{$sender->getCanonicalName()}</b></a> отправил вам {$notification->getDateTime()} подарок. <a href="{$sender->getURL()}"><b>{$sender->getCanonicalName()}</b></a> отправил вам {$notification->getDateTime()} подарок.

View file

@ -1,6 +1,6 @@
{var sender = $notification->getModel(1)} {var $sender = $notification->getModel(1)}
{var value = (int) explode(" ", $notification->getData(), 2)[0]} {var $value = (int) explode(" ", $notification->getData(), 2)[0]}
{var message = explode(" ", $notification->getData(), 2)[1]} {var $message = explode(" ", $notification->getData(), 2)[1]}
<a href="{$sender->getURL()}"><b>{$sender->getCanonicalName()}</b></a> {_transferred_to_you} {tr("points_amount", $value)}. <a href="{$sender->getURL()}"><b>{$sender->getCanonicalName()}</b></a> {_transferred_to_you} {tr("points_amount", $value)}.
{if !empty($message)} {if !empty($message)}

View file

@ -1,6 +1,6 @@
{var sender = $notification->getModel(1)} {var $sender = $notification->getModel(1)}
{var value = (int) explode(" ", $notification->getData(), 2)[0]} {var $value = (int) explode(" ", $notification->getData(), 2)[0]}
{var message = explode(" ", $notification->getData(), 2)[1]} {var $message = explode(" ", $notification->getData(), 2)[1]}
<a href="{$sender->getURL()}"><b>{$sender->getCanonicalName()}</b></a> {_increased_your_rating_by} {$value}%. <a href="{$sender->getURL()}"><b>{$sender->getCanonicalName()}</b></a> {_increased_your_rating_by} {$value}%.
{if !empty($message)} {if !empty($message)}

View file

@ -1,7 +1,7 @@
{var microblogEnabled = isset($thisUser) ? $thisUser->hasMicroblogEnabled() : false} {var $microblogEnabled = isset($thisUser) ? $thisUser->hasMicroblogEnabled() : false}
{if $microblogEnabled} {if $microblogEnabled}
{include "post/microblogpost.xml", post => $post, diff => $diff, commentSection => $commentSection} {include "post/microblogpost.xml", post => $post, commentSection => $commentSection}
{else} {else}
{include "post/oldpost.xml", post => $post, diff => $diff} {include "post/oldpost.xml", post => $post}
{/if} {/if}

View file

@ -1,8 +1,8 @@
{var author = $post->getOwner()} {var $author = $post->getOwner()}
{var comments = $post->getLastComments(3)} {var $comments = $post->getLastComments(3)}
{var commentsCount = $post->getCommentsCount()} {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"> <table border="0" style="font-size: 11px;" n:class="post, !$compact ? post-divider, $post->isExplicit() ? post-nsfw">
<tbody> <tbody>
@ -18,8 +18,8 @@
<a href="{$author->getURL()}"><b>{$author->getCanonicalName()}</b></a> <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"> <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()} {if ($onWallOf ?? false) &&!$post->isPostedOnBehalfOfGroup() && $post->getOwnerPost() !== $post->getTargetWall()}
{var wallId = $post->getTargetWall()} {var $wallId = $post->getTargetWall()}
{var wallURL = $wallId > -1 ? "/id$wallId" : "/club" . abs($wallId)} {var $wallURL = $wallId > -1 ? "/id$wallId" : "/club" . abs($wallId)}
на на
<a href="{$wallURL}"> <a href="{$wallURL}">
<b> <b>
@ -68,7 +68,7 @@
&nbsp;! Этот пост был размещён за взятку. &nbsp;! Этот пост был размещён за взятку.
</div> </div>
<div n:if="$post->isSigned()" class="post-signature"> <div n:if="$post->isSigned()" class="post-signature">
{var actualAuthor = $post->getOwner(false)} {var $actualAuthor = $post->getOwner(false)}
<span> <span>
{_author}: {_author}:
<a href="{$actualAuthor->getURL()}"> <a href="{$actualAuthor->getURL()}">
@ -91,7 +91,7 @@
</a> </a>
{if !($forceNoLike ?? false)} {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()}"> <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> <div class="heart" id="{if $liked}liked{/if}"></div>
<span class="likeCnt">{if $post->getLikesCount() > 0}{$post->getLikesCount()}{/if}</span> <span class="likeCnt">{if $post->getLikesCount() > 0}{$post->getLikesCount()}{/if}</span>
@ -106,8 +106,8 @@
{include "../comment.xml", comment => $comment, $compact => true} {include "../comment.xml", comment => $comment, $compact => true}
{/foreach} {/foreach}
<div n:ifset="$thisUser" id="commentTextArea{$commentTextAreaId}" n:attr="style => ($commentsCount == 0 ? 'display: none;')" class="commentsTextFieldWrap"> <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 $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 $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} {include "../textArea.xml", route => $commentsURL, postOpts => false, graffiti => (bool) ovkGetQuirk("comments.allow-graffiti"), post => $post, club => $club}
</div> </div>
</div> </div>

View file

@ -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"> <table border="0" style="font-size: 11px;" n:class="post, $post->isExplicit() ? post-nsfw">
<tbody> <tbody>
@ -15,8 +15,8 @@
<img n:if="$author->isVerified()" class="name-checkmark" src="/assets/packages/static/openvk/img/checkmark.png"> <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"))} {$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()} {if ($onWallOf ?? false) &&!$post->isPostedOnBehalfOfGroup() && $post->getOwnerPost() !== $post->getTargetWall()}
{var wallId = $post->getTargetWall()} {var $wallId = $post->getTargetWall()}
{var wallURL = $wallId > -1 ? "/id$wallId" : "/club" . abs($wallId)} {var $wallURL = $wallId > -1 ? "/id$wallId" : "/club" . abs($wallId)}
на на
<a href="{$wallURL}"> <a href="{$wallURL}">
<b> <b>
@ -50,7 +50,7 @@
&nbsp;! Этот пост был размещён за взятку. &nbsp;! Этот пост был размещён за взятку.
</div> </div>
<div n:if="$post->isSigned()" class="post-signature"> <div n:if="$post->isSigned()" class="post-signature">
{var actualAuthor = $post->getOwner(false)} {var $actualAuthor = $post->getOwner(false)}
<span> <span>
{_author}: {_author}:
<a href="{$actualAuthor->getURL()}"> <a href="{$actualAuthor->getURL()}">
@ -92,7 +92,7 @@
</a> </a>
<div n:if="!($forceNoLike ?? false)" class="like_wrap"> <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()}"> <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> <div class="heart" id="{if $liked}liked{/if}"></div>
<span class="likeCnt">{if $post->getLikesCount() > 0}{$post->getLikesCount()}{/if}</span> <span class="likeCnt">{if $post->getLikesCount() > 0}{$post->getLikesCount()}{/if}</span>

View file

@ -1,5 +1,5 @@
{php if(!isset($GLOBALS["textAreaCtr"])) $GLOBALS["textAreaCtr"] = 10;} {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});"> <div id="write" style="padding: 5px 0;" onfocusin="expand_wall_textarea({$textAreaId});">
<form action="{$route}" method="post" enctype="multipart/form-data" style="margin:0;"> <form action="{$route}" method="post" enctype="multipart/form-data" style="margin:0;">
@ -12,7 +12,7 @@
{_attachment}: <span>(unknown)</span> {_attachment}: <span>(unknown)</span>
</div> </div>
<div n:if="$postOpts ?? true" class="post-opts"> <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 !is_null($thisUser) && !is_null($club ?? NULL) && $owner < 0}
{if $club->canBeModifiedBy($thisUser)} {if $club->canBeModifiedBy($thisUser)}

View file

@ -71,6 +71,8 @@ routes:
handler: "User->twoFactorAuthSettings" handler: "User->twoFactorAuthSettings"
- url: "/settings/2fa/disable" - url: "/settings/2fa/disable"
handler: "User->disableTwoFactorAuth" handler: "User->disableTwoFactorAuth"
- url: "/settings/reset_theme"
handler: "User->resetThemepack"
- url: "/coins_transfer" - url: "/coins_transfer"
handler: "User->coinsTransfer" handler: "User->coinsTransfer"
- url: "/increase_social_credits" - url: "/increase_social_credits"
@ -121,8 +123,10 @@ routes:
handler: "Wall->delete" handler: "Wall->delete"
- url: "/wall{num}_{num}/pin" - url: "/wall{num}_{num}/pin"
handler: "Wall->pin" handler: "Wall->pin"
- url: "/blob_{text}/{text}.{text}" - url: "/blob_{text}/{?path}.{text}"
handler: "Blob->file" handler: "Blob->file"
placeholders:
path: "[A-z0-9\\-_\\/]{3,}"
- url: "/themepack/{text}/{?version}/{?resClass}/{?any}" - url: "/themepack/{text}/{?version}/{?resClass}/{?any}"
handler: "Themepacks->resource" handler: "Themepacks->resource"
placeholders: placeholders:
@ -301,6 +305,8 @@ routes:
handler: "About->robotsTxt" handler: "About->robotsTxt"
- url: "/humans.txt" - url: "/humans.txt"
handler: "About->humansTxt" handler: "About->humansTxt"
- url: "/dev"
handler: "About->dev"
- url: "/{?shortCode}" - url: "/{?shortCode}"
handler: "UnknownTextRouteStrategy->delegate" handler: "UnknownTextRouteStrategy->delegate"
placeholders: placeholders:

Binary file not shown.

BIN
Web/static/audio/notify.mp3 Normal file

Binary file not shown.

View file

@ -2,7 +2,7 @@
/* Design belongs to Pavel Durov & VK Group */ /* Design belongs to Pavel Durov & VK Group */
.post { .post {
padding: 5px 0 5px 0; padding: 5px 0;
} }
.post-divider { .post-divider {
@ -12,7 +12,7 @@
.post-author { .post-author {
background-color: transparent; background-color: transparent;
border: none; border: none;
padding: 0 3px 3px 3px; padding: 0 3px 3px;
} }
.post-author .date { .post-author .date {
@ -25,7 +25,7 @@
} }
.post-content .text { .post-content .text {
padding: 0 4px 0 4px; padding: 0 4px;
} }
.post-menu { .post-menu {
@ -37,7 +37,7 @@
} }
.comment { .comment {
padding: 5px 0 0 0; padding: 5px 0 0;
border-top: 1px #ddd solid; border-top: 1px #ddd solid;
} }
@ -46,16 +46,16 @@
} }
.repost-icon { .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; height: 12px;
margin: 2px 3px 0px; margin: 2px 3px 0;
width: 11px; width: 11px;
} }
.heart { .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; height: 10px;
margin: 2px 3px 0px; margin: 2px 3px 0;
width: 11px; width: 11px;
float: none; float: none;
opacity: 0.4; opacity: 0.4;
@ -73,24 +73,25 @@
opacity: 0.4 !important; opacity: 0.4 !important;
} }
.post-share-button, .post-like-button { .post-share-button,
.post-like-button {
display: flex; display: flex;
padding: 2px; padding: 2px;
border-radius: 2px; border-radius: 2px;
transition-duration: 0.2s; 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); background-color: rgb(240, 240, 240);
} }
.post-author .delete { .post-author .delete {
float: right; float: right;
display: inline-block;
height: 16px; height: 16px;
width: 16px; width: 16px;
overflow: auto; 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; opacity: 0.1;
transition-duration: 0.3s; transition-duration: 0.3s;
} }
@ -101,11 +102,10 @@
.post-author .pin { .post-author .pin {
float: right; float: right;
display: inline-block;
height: 16px; height: 16px;
width: 16px; width: 16px;
overflow: auto; 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; opacity: 0.1;
transition-duration: 0.3s; transition-duration: 0.3s;
} }
@ -117,7 +117,7 @@
.expand_button { .expand_button {
background-color: #eee; background-color: #eee;
width: 100%; width: 100%;
display: inline-block;; display: inline-block;
height: 30px; height: 30px;
line-height: 28px; line-height: 28px;
text-align: center; text-align: center;

View file

@ -13,12 +13,6 @@ body {
word-wrap: break-word; word-wrap: break-word;
} }
span {
padding: 0 0 2px;
color: gray;
font-weight: bold;
}
.nobold, .nobold,
nobold { nobold {
font-weight: normal; font-weight: normal;
@ -48,9 +42,9 @@ p {
position: relative; position: relative;
width: 791px; width: 791px;
height: 45px; height: 45px;
background: url('../img/header.png');
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: 0; background-position: 0;
background: url('../img/header.png');
} }
.page_custom_header { .page_custom_header {
@ -59,7 +53,7 @@ p {
#page_act { #page_act {
border-bottom: 1px solid #d5dde6; border-bottom: 1px solid #d5dde6;
padding: 2px 10px 5px 10px; padding: 2px 10px 5px;
color: #2B587A; color: #2B587A;
width: 608px; width: 608px;
margin-left: -10px; margin-left: -10px;
@ -95,8 +89,8 @@ p {
display: inline-block; display: inline-block;
height: 29px; height: 29px;
padding: 11px 4px 0 7px; padding: 11px 4px 0 7px;
background-size: 1.5px 41px;
background: url('../img/divider.png') no-repeat; background: url('../img/divider.png') no-repeat;
background-size: 1.5px 41px;
} }
.header_navigation .link a { .header_navigation .link a {
@ -164,7 +158,6 @@ p {
padding: 3px 3px 3px 6px; padding: 3px 3px 3px 6px;
text-decoration: none; text-decoration: none;
border-top: 1px solid #fff; border-top: 1px solid #fff;
/* fix */
color: #000; color: #000;
} }
@ -184,17 +177,17 @@ p {
.wrap1 { .wrap1 {
border: 1px solid #EBF0F4; border: 1px solid #EBF0F4;
border-top: 0px; border-top: 0;
width: auto; width: auto;
} }
.wrap2 { .wrap2 {
border-right: 1px solid #F6F8FA; border-right: 1px solid #F6F8FA;
border-top: 0px; border-top: 0;
} }
.page_yellowheader { .page_yellowheader {
padding: 4px 10px 4px; padding: 4px 10px;
font-weight: bold; font-weight: bold;
background: url('../img/header_yellow.png') repeat-x; background: url('../img/header_yellow.png') repeat-x;
background-color: #EEE5B8; background-color: #EEE5B8;
@ -405,7 +398,7 @@ table {
.page_status { .page_status {
font-weight: normal; font-weight: normal;
font-size: 11px; font-size: 11px;
padding: 3px 1px 3px; padding: 3px 1px;
color: #000; color: #000;
width: 380px; width: 380px;
height: auto !important; height: auto !important;
@ -442,9 +435,9 @@ table {
outline: none; outline: none;
white-space: nowrap; white-space: nowrap;
background: #595959; background: #595959;
background-position: 0px -16px; background-position: 0 -16px;
color: #fff; color: #fff;
padding: 4px 8px 4px; padding: 4px 8px;
text-shadow: 0 1px 0 #686868; text-shadow: 0 1px 0 #686868;
cursor: pointer; cursor: pointer;
text-decoration: none; text-decoration: none;
@ -477,7 +470,7 @@ input[type=radio] {
outline: none; outline: none;
cursor: pointer; cursor: pointer;
vertical-align: middle; vertical-align: middle;
margin: 4px 3px 3px 3px; margin: 4px 3px 3px;
} }
input[type=checkbox] { input[type=checkbox] {
@ -520,17 +513,13 @@ input[type=radio]:checked {
width: 200px; width: 200px;
} }
.right_big_block {
width: 399px;
float: right;
}
.content_title_expanded { .content_title_expanded {
background-image: url('../img/flex_arrow_open2.png'); background-image: url('../img/flex_arrow_open2.png');
background-repeat: no-repeat; background-repeat: no-repeat;
background-color: #e6e6e6; background-color: #e6e6e6;
border-top: #8B8B8B solid 1px; border-top: #8B8B8B solid 1px;
padding: 3px 8px 3px 24px; padding: 3px 8px 3px 24px;
margin-top: 5px;
font-weight: bold; font-weight: bold;
color: #626262; color: #626262;
font-size: 11px; font-size: 11px;
@ -554,7 +543,6 @@ input[type=radio]:checked {
.content_subtitle { .content_subtitle {
background-color: #F0F0F0; background-color: #F0F0F0;
padding: 0;
display: block; display: block;
font-size: 11px; font-size: 11px;
border-bottom: 1px solid #EEEEEE; border-bottom: 1px solid #EEEEEE;
@ -568,7 +556,7 @@ input[type=radio]:checked {
} }
.content-withouttop { .content-withouttop {
padding-top: 0px; padding-top: 0;
} }
input[type="text"], input[type="text"],
@ -595,8 +583,8 @@ h4 {
color: #45688E; color: #45688E;
font-size: 12px; font-size: 12px;
font-weight: bold; font-weight: bold;
margin: 0px; margin: 0;
padding: 0px 0px 3px; padding: 0 0 3px;
font-family: verdana, arial, sans-serif; font-family: verdana, arial, sans-serif;
} }
@ -619,7 +607,7 @@ h4 {
border-top: #8B8B8B solid 1px; border-top: #8B8B8B solid 1px;
border-bottom: #ECECEC solid 1px; border-bottom: #ECECEC solid 1px;
font-size: 11px; font-size: 11px;
padding: 3px 5px 3px; padding: 3px 5px;
line-height: 125%; line-height: 125%;
} }
@ -769,7 +757,7 @@ span {
} }
.content_list .cl_element .cl_avatar { .content_list .cl_element .cl_avatar {
padding: 7px 7px 0 7px; padding: 7px 7px 0;
text-align: center; text-align: center;
} }
@ -807,13 +795,6 @@ table.User {
width: 603px; width: 603px;
} }
.container_gray .content {
background: #fff;
padding: 5px;
border: #DEDEDE solid 1px;
clear: both;
}
.tabs { .tabs {
border-bottom: 1px solid #707070; border-bottom: 1px solid #707070;
padding: 0 10px; padding: 0 10px;
@ -832,7 +813,7 @@ table.User {
display: inline-block; display: inline-block;
padding: 5px 10px; padding: 5px 10px;
margin-right: 3px; margin-right: 3px;
border-radius: 3px 3px 0px 0px; border-radius: 3px 3px 0 0;
} }
.tab:hover { .tab:hover {
@ -995,11 +976,6 @@ table.User {
color: #404036; color: #404036;
} }
.messenger-app--messages,
.messenger-app--input {
padding: 10px;
}
.messenger-app--messages, .messenger-app--messages,
.messenger-app--input { .messenger-app--input {
padding: 10px 70px; padding: 10px 70px;
@ -1021,11 +997,6 @@ table.User {
margin-bottom: 1.2rem; margin-bottom: 1.2rem;
} }
.messenger-app--messages---message .ava,
.messenger-app--input>.ava {
max-width: 64px;
}
.messenger-app--messages---message .ava, .messenger-app--messages---message .ava,
.messenger-app--input>.ava { .messenger-app--input>.ava {
width: 52px; width: 52px;
@ -1074,6 +1045,7 @@ table.User {
box-sizing: border-box; box-sizing: border-box;
padding: 0 10px; padding: 0 10px;
width: calc(100% - 128px); width: calc(100% - 128px);
float: right;
} }
.messenger-app--input---messagebox textarea { .messenger-app--input---messagebox textarea {
@ -1083,10 +1055,6 @@ table.User {
margin-bottom: 8px !important; margin-bottom: 8px !important;
} }
.messenger-app--input---messagebox {
float: right;
}
.messenger-app--input .blocked { .messenger-app--input .blocked {
width: 100%; width: 100%;
height: 100%; height: 100%;
@ -1190,16 +1158,16 @@ textarea {
#faqhead { #faqhead {
background: #fbf3c3; background: #fbf3c3;
margin: 0px 5px 0px 5px; margin: 0 5px;
padding: 5px; padding: 5px;
font-weight: bold; font-weight: bold;
border: 1px solid #d7cf9e; border: 1px solid #d7cf9e;
border-bottom: 0px; border-bottom: 0;
} }
#faqcontent { #faqcontent {
background: #fafafa; background: #fafafa;
margin: 0px 5px 10px 5px; margin: 0 5px 10px;
padding: 5px 5px 5px 10px; padding: 5px 5px 5px 10px;
border: 1px solid #ddd; border: 1px solid #ddd;
} }
@ -1307,12 +1275,6 @@ body.scrolled .toTop:hover {
vertical-align: super; 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) { .ugc-table.slim tr>td:nth-of-type(1) {
width: unset; width: unset;
} }
@ -1378,9 +1340,9 @@ body.scrolled .toTop:hover {
} }
.heart { .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; height: 10px;
margin: 2px 3px 0px; margin: 2px 3px 0;
width: 11px; width: 11px;
float: left; float: left;
opacity: 0.4; opacity: 0.4;
@ -1400,10 +1362,6 @@ body.scrolled .toTop:hover {
opacity: 1 !important; opacity: 1 !important;
} }
.content_title_expanded {
margin-top: 5px;
}
.page-wrap { .page-wrap {
border-bottom: solid 1px #C3CAD2; border-bottom: solid 1px #C3CAD2;
border-left: solid 1px #DAE1E8; border-left: solid 1px #DAE1E8;
@ -1411,33 +1369,12 @@ body.scrolled .toTop:hover {
padding: 10px; 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 { .ugc-table td {
vertical-align: top !important; vertical-align: top !important;
font-size: 11px; font-size: 11px;
line-height: 13px; line-height: 13px;
margin: 0px; margin: 0;
padding: 1px 0px 1px 0px; padding: 1px 0;
} }
.label { .label {
@ -1457,47 +1394,44 @@ body.scrolled .toTop:hover {
} }
#basicInfo { #basicInfo {
padding: 5px 0px 15px 8px; padding: 5px 0 15px 8px;
} }
.accountInfo { .accountInfo {
padding: 0px; padding: 0;
margin: 0px 0px 0px 8px; margin: 0 0 0 8px;
border-bottom: solid 1px #DAE1E8; border-bottom: solid 1px #DAE1E8;
display: block; display: block;
} }
.profileName { .profileName {
/* width: 225px; */
color: #45688E; color: #45688E;
font-size: 11px; font-size: 11px;
font-weight: bold; font-weight: bold;
margin: 0px; margin: 0;
/* padding: 2px 5px 0px 0px; */
} }
.profileName h2 { .profileName h2 {
color: #45688E; color: #45688E;
font-size: 13px; font-size: 13px;
padding-bottom: 0px; margin: 0;
margin: 0px; padding: 0;
padding: 0px;
} }
.notes_titles { .notes_titles {
margin: 0px; margin: 0;
padding: 0px; padding: 0;
list-style: none; list-style: none;
} }
.written { .written {
background: url('/assets/packages/static/openvk/img/note.gif') no-repeat 0px 1px; background: url('/assets/packages/static/openvk/img/note.gif') no-repeat 0 1px;
padding: 0px 0px 6px 22px; padding: 0 0 6px 22px;
} }
.written a { .written a {
display: block; display: block;
padding: 0px 0px 1px 0px; padding: 0 0 1px;
} }
.notes_titles small { .notes_titles small {
@ -1517,8 +1451,8 @@ body.scrolled .toTop:hover {
} }
.right_big_block h4 { .right_big_block h4 {
margin: 1px 0px 0px; margin: 1px 0 0;
padding: 4px 0px 2px !important; padding: 4px 0 2px !important;
} }
.knowledgeBaseArticle ul { .knowledgeBaseArticle ul {
@ -1577,7 +1511,7 @@ body.scrolled .toTop:hover {
align-content: center; align-content: center;
display: flex; display: flex;
padding: 2px; 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; background-color: #000;
} }
@ -1648,17 +1582,26 @@ body.scrolled .toTop:hover {
color: #58462a; color: #58462a;
} }
.group-alert {
margin-bottom: 8px;
padding: 4px;
border: 1px solid #c3a476;
font-weight: 900;
background-color: #f3ddbd;
color: #58462a;
}
.knowledgeBaseArticle { .knowledgeBaseArticle {
margin-top: -11px; margin-top: -11px;
/* this is very stupid fix but nah */ /* this is very stupid fix but nah */
} }
.avatar-list { .avatar-list {
padding: 4px 8px 4px 8px; padding: 4px 8px;
} }
.avatar-list-item { .avatar-list-item {
padding: 4px 0 4px 0; padding: 4px 0;
} }
.avatar-list-item::after { .avatar-list-item::after {
@ -1763,9 +1706,9 @@ body.scrolled .toTop:hover {
outline: none; outline: none;
white-space: nowrap; white-space: nowrap;
background: #595959; background: #595959;
background-position: 0px -16px; background-position: 0 -16px;
color: #fff; color: #fff;
padding: 4px 8px 4px; padding: 4px 8px;
text-shadow: 0 1px 0 #686868; text-shadow: 0 1px 0 #686868;
cursor: pointer; cursor: pointer;
text-decoration: none; text-decoration: none;
@ -1810,7 +1753,7 @@ body.scrolled .toTop:hover {
height: 16px; height: 16px;
width: 16px; width: 16px;
overflow: auto; 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; vertical-align: middle;
} }
@ -1858,7 +1801,7 @@ body.scrolled .toTop:hover {
background: #f7f7f7; background: #f7f7f7;
border-bottom: solid 1px #DAE1E8; border-bottom: solid 1px #DAE1E8;
border-top: solid 1px #45688E; border-top: solid 1px #45688E;
padding: 4px 6px 5px 6px; padding: 4px 6px 5px;
} }
.note_header .note_title { .note_header .note_title {
@ -1867,18 +1810,18 @@ body.scrolled .toTop:hover {
font-weight: bold; font-weight: bold;
line-height: 15px; line-height: 15px;
margin: 0; margin: 0;
padding: 0 0 1px 0; padding: 0 0 1px;
} }
.note_footer { .note_footer {
border-top: 1px solid #ddd; border-top: 1px solid #ddd;
clear: both; clear: both;
margin-top: 10px; margin-top: 10px;
padding: 0px 2px 0px 6px; padding: 0 2px 0 6px;
} }
.comments_count { .comments_count {
padding: 5px 0px 0px 0px; padding: 5px 0 0;
} }
.groups_options { .groups_options {
@ -1917,7 +1860,7 @@ table td[width="120"] {
} }
.profile_thumb { .profile_thumb {
padding: 0px 10px 0px 0px; padding: 0 10px 0 0;
width: 50px; width: 50px;
display: inline-block; display: inline-block;
vertical-align: top; vertical-align: top;
@ -1941,23 +1884,6 @@ table td[width="120"] {
padding: 3px 7px; 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 { .mb_tab#active {
background-color: #898989; background-color: #898989;
} }
@ -1970,15 +1896,8 @@ table td[width="120"] {
color: white; color: white;
} }
.profile_thumb {
padding: 0px 10px 0px 0px;
width: 50px;
display: inline-block;
vertical-align: top;
}
.border-block { .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; width: 300px;
padding: 20px; padding: 20px;
} }
@ -1986,3 +1905,12 @@ table td[width="120"] {
.center { .center {
margin: 0 auto; margin: 0 auto;
} }
#votesBalance {
margin-top: 50px;
padding: 7px;
background-color: #f6f6f6;
border-bottom: 1.5px solid #707070;
text-align: center;
user-select: none;
}

View file

@ -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() { function __actualPlayNotifSound() {
createjs.Sound.play("notification"); createjs.Sound.play("notification");

View file

@ -117,3 +117,8 @@ function setupWallPostInputHandlers(id) {
// textArea.style.height = (newHeight > originalHeight ? (newHeight + boost) : originalHeight) + "px"; // textArea.style.height = (newHeight > originalHeight ? (newHeight + boost) : originalHeight) + "px";
}); });
} }
u("#write > form").on("keydown", function(event) {
if(event.ctrlKey && event.keyCode === 13)
this.submit();
});

View file

@ -2,7 +2,33 @@ Function.noop = () => {};
var _n_counter = 0; 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) { if(avatar != null) {
avatar = '<avatar>' + avatar = '<avatar>' +
'<img src="' + avatar + '">' + '<img src="' + avatar + '">' +
@ -40,7 +66,14 @@ function NewNotification(title, body, avatar = null, callback = () => {}, time =
setTimeout(() => {getPrototype().remove()}, 500); 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) { notification.children('notification_title').children('a.close').on('click', function(e) {
__closeNotification(); __closeNotification();

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

View file

@ -16,7 +16,9 @@
"erusev/parsedown": "dev-master", "erusev/parsedown": "dev-master",
"bhaktaraz/php-rss-generator": "dev-master", "bhaktaraz/php-rss-generator": "dev-master",
"ext-simplexml": "*", "ext-simplexml": "*",
"symfony/console": "5.4.x-dev" "symfony/console": "5.4.x-dev",
"wapmorgan/morphos": "dev-master",
"ext-sodium": "*"
}, },
"minimum-stability": "dev" "minimum-stability": "dev"
} }

79
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "878bd996183ccbb15637a7399ba03ab9", "content-hash": "63feb555e36a6e7ab5a0a5ec71adecdd",
"packages": [ "packages": [
{ {
"name": "al/emoji-detector", "name": "al/emoji-detector",
@ -2222,6 +2222,80 @@
}, },
"time": "2018-09-26T17:10:59+00:00" "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", "name": "whichbrowser/parser",
"version": "dev-master", "version": "dev-master",
@ -2356,7 +2430,8 @@
"vearutop/php-obscene-censor-rus": 20, "vearutop/php-obscene-censor-rus": 20,
"erusev/parsedown": 20, "erusev/parsedown": 20,
"bhaktaraz/php-rss-generator": 20, "bhaktaraz/php-rss-generator": 20,
"symfony/console": 20 "symfony/console": 20,
"wapmorgan/morphos": 20
}, },
"prefer-stable": false, "prefer-stable": false,
"prefer-lowest": false, "prefer-lowest": false,

View file

@ -8,6 +8,10 @@ chandler:
adminUrl: "/chandlerd" adminUrl: "/chandlerd"
exposeChandler: true exposeChandler: true
extensions:
path: null
allEnabled: false
database: database:
dsn: "mysql:unix_socket=/var/run/mysql/mysql.sock;dbname=openvk" dsn: "mysql:unix_socket=/var/run/mysql/mysql.sock;dbname=openvk"
user: "root" user: "root"
@ -16,3 +20,5 @@ chandler:
security: security:
secret: "081906e04f2921e48751fbc5df44dbbcd7f6ecba065ade3d8ea28034cb8d6db24da10965845b5f3376847674e3bce61b5c0e439d12eef3c00d30f3b953657cac" secret: "081906e04f2921e48751fbc5df44dbbcd7f6ecba065ade3d8ea28034cb8d6db24da10965845b5f3376847674e3bce61b5c0e439d12eef3c00d30f3b953657cac"
sessionDuration: 14 sessionDuration: 14
csrfProtection: "permissive"
extendedValidation: false

View 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"

View file

@ -1,10 +1,10 @@
#!/bin/tcsh #!/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 # / / | ` \ # # Copyright (c) 2020 OpenVK contributors # / / | ` \ #
# ------------------------------------------------------------- # O O ) / | # # ------------------------------------------------------------- # O O ) / | #
# # `-^--'`< ' # # # `-^--'`< ' #
@ -27,28 +27,27 @@ if ($? == 1) then
endif endif
set osVer = `freebsd-version -r` set osVer = `freebsd-version -r`
if ($osVer !~ "12.*") then if ($osVer !~ "13.*") then
echo "Fatal Error: This installation supports only FreeBSD 12, but you have FreeBSD $osVer installed." echo "Fatal Error: This installation supports only FreeBSD 13, but you have FreeBSD $osVer installed."
exit 201 exit 201
endif endif
# Update system cd /tmp
pkg update mkdir ovkinstall
pkg upgrade cd ovkinstall
# Install programming languages and Git # Install required packages
yes | pkg install git 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
yes | pkg install php74 rehash
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 package managers
npm i -g yarn
curl -LO https://getcomposer.org/installer curl -LO https://getcomposer.org/installer
php ./installer --install-dir=/bin --filename=composer --preview php ./installer --install-dir=/bin --filename=composer --preview
rm -f ./installer rm -f ./installer
yes | pkg install node npm rehash
npm i -g yarn
# Download OVK distro # Download OVK distro
cd /tmp
git clone https://github.com/openvk/openvk.git git clone https://github.com/openvk/openvk.git
# Install chandler # Install chandler
@ -58,7 +57,7 @@ git clone https://github.com/openvk/chandler.git
cd chandler cd chandler
yes | composer install 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: . chown -R www: .
chmod -R 777 . chmod -R 777 .
@ -75,7 +74,7 @@ cd /opt/chandler
ln -s /opt/chandler/extensions/available/commitcaptcha /opt/chandler/extensions/enabled/commitcaptcha ln -s /opt/chandler/extensions/available/commitcaptcha /opt/chandler/extensions/enabled/commitcaptcha
# Install OpenVK # 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 ln -s /opt/chandler/extensions/available/openvk /opt/chandler/extensions/enabled/openvk
cd ./extensions/available/openvk cd ./extensions/available/openvk
@ -84,36 +83,46 @@ yes | composer install
cd Web/static/js cd Web/static/js
yarn install 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 ../../../ cd ../../../
chown -R www: . chown -R www: .
chmod -R 777 . chmod -R 777 .
# Install MySQL # Setup databases
yes | pkg install mariadb105-server mariadb105-client
sysrc mysql_enable="yes" sysrc mysql_enable="yes"
service mysql-server start 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 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 < install/init-db.sql
mysql -p'justMonika' openvk < /tmp/openvk/install/init-static-db.sql mysql -p'justMonika' openvk < /tmp/ovkinstall/openvk/install/init-static-db.sql
mysql -p'justMonika' openvk-eventdb < /tmp/openvk/install/init-event-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 # Alias folders
rm -rf /usr/local/www/apache24/data rm -rf /usr/local/www/apache24/data
ln -s /opt/chandler/htdocs /usr/local/www/apache24/data ln -s /opt/chandler/htdocs /usr/local/www/apache24/data
# Configure Apache # Configure Apache
cp /tmp/openvk/install/automated/common/httpd.conf /usr/local/etc/apache24/httpd.conf cp /tmp/ovkinstall/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-php.conf /usr/local/etc/apache24/Includes/php.conf
sysrc apache24_enable="yes" sysrc apache24_enable="yes"
service apache24 start service apache24 start
# Cleanup
rm -rf /opt/ovkinstall
# Enjoy # Enjoy
echo "~================= OpenVK 2 Installed =================~" echo "~================= OpenVK 2 Installed =================~"
echo " Use it: http://localhost:80/ " echo " Use it: http://localhost:80/ "

View file

@ -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;

View file

@ -1 +1 @@
ALTER TABLE groups ADD COLUMN owner_comment VARCHAR(36) AFTER owner; ALTER TABLE `groups` ADD COLUMN owner_comment VARCHAR(36) AFTER owner;

View file

@ -3,7 +3,7 @@ ALTER TABLE `profiles` ADD `activated` tinyint(3) NULL DEFAULT '1' AFTER `2fa_se
CREATE TABLE IF NOT EXISTS `email_verifications` ( CREATE TABLE IF NOT EXISTS `email_verifications` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`profile` bigint(20) unsigned NOT NULL, `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, `timestamp` bigint(20) unsigned NOT NULL,
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_nopad_ci; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;

View 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`;

View file

@ -0,0 +1 @@
ALTER TABLE `groups` ADD `alert` TEXT NULL DEFAULT NULL;

View file

@ -558,6 +558,8 @@
"points" = "Votes"; "points" = "Votes";
"points_count" = "votes"; "points_count" = "votes";
"on_your_account" = "on your account"; "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"; "vouchers" = "Vouchers";
"have_voucher" = "Have voucher"; "have_voucher" = "Have voucher";
@ -779,6 +781,7 @@
"error_new_password" = "New password does not match"; "error_new_password" = "New password does not match";
"error_shorturl_incorrect" = "The short address has an incorrect format."; "error_shorturl_incorrect" = "The short address has an incorrect format.";
"error_repost_fail" = "Failed to share post"; "error_repost_fail" = "Failed to share post";
"error_data_too_big" = "Attribute '$1' must be at most $2 $3 long";
"forbidden" = "Access error"; "forbidden" = "Access error";
"forbidden_comment" = "This user's privacy settings do not allow you to look at his page."; "forbidden_comment" = "This user's privacy settings do not allow you to look at his page.";
@ -858,6 +861,8 @@
"rules" = "Rules"; "rules" = "Rules";
"most_popular_groups" = "Most popular groups"; "most_popular_groups" = "Most popular groups";
"on_this_instance_are" = "On this instance are:"; "on_this_instance_are" = "On this instance are:";
"about_links" = "Links";
"instance_links" = "Instance links:";
"about_users_one" = "<b>1</b> user"; "about_users_one" = "<b>1</b> user";
"about_users_other" = "<b>$1</b> users"; "about_users_other" = "<b>$1</b> users";

Some files were not shown because too many files have changed in this diff Show more