Compare commits

...

13 commits

Author SHA1 Message Date
n1rwana
19dee0eb05
Merge a16e15eaef into 3ceb27e532 2024-11-03 08:09:14 +00:00
3ceb27e532
build(composer.lock): update dependencies 2024-11-03 00:20:54 +03:00
99a2e3a8e6
fix(docker): set openvk dir as workdir
So that opening a shell with `docker compose exec openvk bash` would lead to openvk dir instead of ~/html which is not used
2024-11-03 00:05:40 +03:00
mrilyew
341226cac5 wall: fix 500 when no user 2024-11-02 16:31:35 +03:00
9b53839192
ci(build-base): add ability to manually dispatch builds 2024-11-02 12:43:11 +03:00
mrilyew
fab39bd7fd
Posts: add source param (#934)
* Chopin

- Полностью переписана та часть где про источник поста
- Исправлен метод video.search
- Сокращено число запросов в БД у шаблона поста
- Удалена ссылка на прикреплятор заметок потому что low quality
- Исправлен баг с прикреплённой заметкой в api, но только если ты указал версию.
- Исправлены проблемы с кешированными спрайтшитами

* Chopin 2
2024-11-01 14:46:41 +03:00
ayato
9b220a88db
locales/en.strings: Rephrasing some strings and grammar check (#1098)
* locales: English: fix grammar

* locales: English: fix confusing labels in the repost modal

Clarified modal phrasing when reposting a user's post. The previous wording, 'Share to user's wall,' was ambiguous and could be interpreted as either sharing to your own wall or the original user's wall. Updated the language to make it clear that the post will be shared to your wall.

---------

Co-authored-by: Vladimir Barinov <veselcraft@icloud.com>
2024-11-01 14:00:09 +03:00
ayato
d1bcdaf7d7
Link directly to interests section of the edit page in completeness gauge (#1113) 2024-11-01 13:58:14 +03:00
f83c45ead9
build(docker): remove version from compose file and add name 2024-10-31 12:58:10 +03:00
Jillian Österreich
96dad033ba
fix(theme-midnight): bump version to 0.0.3.0 2024-10-30 18:59:03 +07:00
b557f42daa
build: add additional compose file for devs 2024-10-29 22:11:06 +03:00
Jillian Österreich
250c022bde
docs(docker): improve instructions 2024-10-30 00:16:06 +07:00
n1rwana
a16e15eaef
Фикс проверки заблокированных ссылок 2023-08-05 14:49:41 +03:00
40 changed files with 739 additions and 422 deletions

View file

@ -2,7 +2,8 @@ name: Build base images
on: on:
schedule: schedule:
- cron: '0 0 * * *' - cron: "0 0 * * *"
workflow_dispatch:
env: env:
BASE_IMAGE_NAME: php BASE_IMAGE_NAME: php
@ -16,10 +17,10 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
with: with:
lfs: false lfs: false
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v2 uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx - name: Set up Docker Buildx
id: buildx id: buildx
uses: docker/setup-buildx-action@v2 uses: docker/setup-buildx-action@v2
@ -38,7 +39,7 @@ jobs:
IMAGE_NAME=ghcr.io/${{ steps.repositorystring.outputs.lowercase }}/$BASE_IMAGE_NAME:$BASE_IMAGE_VERSION-cli IMAGE_NAME=ghcr.io/${{ steps.repositorystring.outputs.lowercase }}/$BASE_IMAGE_NAME:$BASE_IMAGE_VERSION-cli
docker buildx build --platform linux/amd64,linux/arm64 -t $IMAGE_NAME . --push -f install/automated/docker/base-php-cli.Dockerfile --build-arg VERSION=$BASE_IMAGE_VERSION docker buildx build --platform linux/amd64,linux/arm64 -t $IMAGE_NAME . --push -f install/automated/docker/base-php-cli.Dockerfile --build-arg VERSION=$BASE_IMAGE_VERSION
build-apache: build-apache:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -46,14 +47,14 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
with: with:
lfs: false lfs: false
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v2 uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx - name: Set up Docker Buildx
id: buildx id: buildx
uses: docker/setup-buildx-action@v2 uses: docker/setup-buildx-action@v2
- name: Change repository string to lowercase - name: Change repository string to lowercase
id: repositorystring id: repositorystring
uses: Entepotenz/change-string-case-action-min-dependencies@v1.1.0 uses: Entepotenz/change-string-case-action-min-dependencies@v1.1.0

View file

@ -74,7 +74,7 @@ final class Video extends VKAPIRequestHandler
$return_items = []; $return_items = [];
$profiles = []; $profiles = [];
$groups = []; $groups = [];
foreach($items as $item) foreach($items as $item) {
$return_item = $item->getApiStructure($this->getUser()); $return_item = $item->getApiStructure($this->getUser());
$return_item = $return_item->video; $return_item = $return_item->video;
$return_items[] = $return_item; $return_items[] = $return_item;
@ -85,6 +85,7 @@ final class Video extends VKAPIRequestHandler
else else
$groups[] = abs($return_item['owner_id']); $groups[] = abs($return_item['owner_id']);
} }
}
if($extended) { if($extended) {
$profiles = array_unique($profiles); $profiles = array_unique($profiles);

View file

@ -102,7 +102,14 @@ final class Wall extends VKAPIRequestHandler
} else if ($attachment instanceof \openvk\Web\Models\Entities\Video) { } else if ($attachment instanceof \openvk\Web\Models\Entities\Video) {
$attachments[] = $attachment->getApiStructure($this->getUser()); $attachments[] = $attachment->getApiStructure($this->getUser());
} else if ($attachment instanceof \openvk\Web\Models\Entities\Note) { } else if ($attachment instanceof \openvk\Web\Models\Entities\Note) {
$attachments[] = $attachment->toVkApiStruct(); if(VKAPI_DECL_VER === '4.100') {
$attachments[] = $attachment->toVkApiStruct();
} else {
$attachments[] = [
'type' => 'note',
'note' => $attachment->toVkApiStruct()
];
}
} else if ($attachment instanceof \openvk\Web\Models\Entities\Audio) { } else if ($attachment instanceof \openvk\Web\Models\Entities\Audio) {
$attachments[] = [ $attachments[] = [
"type" => "audio", "type" => "audio",
@ -188,6 +195,9 @@ final class Wall extends VKAPIRequestHandler
] ]
]; ];
if($post->hasSource())
$post_temp_obj->copyright = $post->getVkApiCopyright();
if($signerId) if($signerId)
$post_temp_obj->signer_id = $signerId; $post_temp_obj->signer_id = $signerId;
@ -291,7 +301,14 @@ final class Wall extends VKAPIRequestHandler
} else if ($attachment instanceof \openvk\Web\Models\Entities\Video) { } else if ($attachment instanceof \openvk\Web\Models\Entities\Video) {
$attachments[] = $attachment->getApiStructure($this->getUser()); $attachments[] = $attachment->getApiStructure($this->getUser());
} else if ($attachment instanceof \openvk\Web\Models\Entities\Note) { } else if ($attachment instanceof \openvk\Web\Models\Entities\Note) {
$attachments[] = $attachment->toVkApiStruct(); if(VKAPI_DECL_VER === '4.100') {
$attachments[] = $attachment->toVkApiStruct();
} else {
$attachments[] = [
'type' => 'note',
'note' => $attachment->toVkApiStruct()
];
}
} else if ($attachment instanceof \openvk\Web\Models\Entities\Audio) { } else if ($attachment instanceof \openvk\Web\Models\Entities\Audio) {
$attachments[] = [ $attachments[] = [
"type" => "audio", "type" => "audio",
@ -373,6 +390,9 @@ final class Wall extends VKAPIRequestHandler
] ]
]; ];
if($post->hasSource())
$post_temp_obj->copyright = $post->getVkApiCopyright();
if($signerId) if($signerId)
$post_temp_obj->signer_id = $signerId; $post_temp_obj->signer_id = $signerId;
@ -543,6 +563,12 @@ final class Wall extends VKAPIRequestHandler
$post->setFlags($flags); $post->setFlags($flags);
$post->setApi_Source_Name($this->getPlatform()); $post->setApi_Source_Name($this->getPlatform());
if(!is_null($copyright) && !empty($copyright)) {
try {
$post->setSource($copyright);
} catch(\Throwable) {}
}
if($owner_id < 0 && !$wallOwner->canBeModifiedBy($this->getUser()) && $wallOwner->getWallType() == 2) if($owner_id < 0 && !$wallOwner->canBeModifiedBy($this->getUser()) && $wallOwner->getWallType() == 2)
$post->setSuggested(1); $post->setSuggested(1);
@ -558,11 +584,11 @@ final class Wall extends VKAPIRequestHandler
# Пример: photo1_1 # Пример: photo1_1
if(sizeof($attachmentsArr) > 10) if(sizeof($attachmentsArr) > 10)
$this->fail(50, "Error: too many attachments"); $this->fail(50, "Too many attachments");
preg_match_all("/poll/m", $attachments, $matches, PREG_SET_ORDER, 0); preg_match_all("/poll/m", $attachments, $matches, PREG_SET_ORDER, 0);
if(sizeof($matches) > 1) if(sizeof($matches) > 1)
$this->fail(85, "Error: too many polls"); $this->fail(85, "Too many polls");
foreach($attachmentsArr as $attac) { foreach($attachmentsArr as $attac) {
$attachmentType = NULL; $attachmentType = NULL;
@ -993,7 +1019,7 @@ final class Wall extends VKAPIRequestHandler
} }
} }
function edit(int $owner_id, int $post_id, string $message = "", string $attachments = "") { function edit(int $owner_id, int $post_id, string $message = "", string $attachments = "", string $copyright = NULL) {
$this->requireUser(); $this->requireUser();
$this->willExecuteWriteAction(); $this->willExecuteWriteAction();
@ -1002,9 +1028,6 @@ final class Wall extends VKAPIRequestHandler
if(!$post || $post->isDeleted()) if(!$post || $post->isDeleted())
$this->fail(102, "Invalid post"); $this->fail(102, "Invalid post");
if(empty($message) && empty($attachments))
$this->fail(100, "Required parameter 'message' missing.");
if(!$post->canBeEditedBy($this->getUser())) if(!$post->canBeEditedBy($this->getUser()))
$this->fail(7, "Access to editing denied"); $this->fail(7, "Access to editing denied");
@ -1012,6 +1035,12 @@ final class Wall extends VKAPIRequestHandler
$post->setContent($message); $post->setContent($message);
$post->setEdited(time()); $post->setEdited(time());
if(!is_null($copyright) && !empty($copyright)) {
try {
$post->setSource($copyright);
} catch(\Throwable) {}
}
$post->save(true); $post->save(true);
# todo добавить такое в веб версию # todo добавить такое в веб версию
@ -1082,6 +1111,63 @@ final class Wall extends VKAPIRequestHandler
return 1; return 1;
} }
function checkCopyrightLink(string $link): int
{
$this->requireUser();
try {
$result = check_copyright_link($link);
} catch(\InvalidArgumentException $e) {
$this->fail(3102, "Specified link is incorrect (can't find source)");
} catch(\LengthException $e) {
$this->fail(3103, "Specified link is incorrect (too long)");
} catch(\LogicException $e) {
$this->fail(3104, "Link is suspicious");
} catch(\Throwable $e) {
$this->fail(3102, "Specified link is incorrect");
}
return 1;
}
function pin(int $owner_id, int $post_id)
{
$this->requireUser();
$this->willExecuteWriteAction();
$post = (new PostsRepo)->getPostById($owner_id, $post_id);
if(!$post || $post->isDeleted())
$this->fail(100, "One of the parameters specified was missing or invalid: post_id is undefined");
if(!$post->canBePinnedBy($this->getUser()))
return 0;
if($post->isPinned())
return 1;
$post->pin();
return 1;
}
function unpin(int $owner_id, int $post_id)
{
$this->requireUser();
$this->willExecuteWriteAction();
$post = (new PostsRepo)->getPostById($owner_id, $post_id);
if(!$post || $post->isDeleted())
$this->fail(100, "One of the parameters specified was missing or invalid: post_id is undefined");
if(!$post->canBePinnedBy($this->getUser()))
return 0;
if(!$post->isPinned())
return 1;
$post->unpin();
return 1;
}
private function getApiPhoto($attachment) { private function getApiPhoto($attachment) {
return [ return [
"type" => "photo", "type" => "photo",

View file

@ -39,7 +39,7 @@ class BannedLink extends RowModel
function getRegexpRule(): string function getRegexpRule(): string
{ {
return addslashes("/" . $this->getDomain() . $this->getRawRegexp() . "/"); return "/^" . $this->getDomain() . "\/" . $this->getRawRegexp() . "$/i";
} }
function getRawRegexp(): string function getRawRegexp(): string

View file

@ -46,8 +46,11 @@ class Comment extends Post
return parent::getOwner($honourFlags, $real); return parent::getOwner($honourFlags, $real);
} }
function canBeDeletedBy(User $user): bool function canBeDeletedBy(User $user = NULL): bool
{ {
if(!$user)
return false;
return $this->getOwner()->getId() == $user->getId() || return $this->getOwner()->getId() == $user->getId() ||
$this->getTarget()->getOwner()->getId() == $user->getId() || $this->getTarget()->getOwner()->getId() == $user->getId() ||
$this->getTarget() instanceof Post && $this->getTarget()->getTargetWall() < 0 && (new Clubs)->get(abs($this->getTarget()->getTargetWall()))->canBeModifiedBy($user) || $this->getTarget() instanceof Post && $this->getTarget()->getTargetWall() < 0 && (new Clubs)->get(abs($this->getTarget()->getTargetWall()))->canBeModifiedBy($user) ||

View file

@ -78,6 +78,40 @@ class Post extends Postable
{ {
return (bool) $this->getRecord()->pinned; return (bool) $this->getRecord()->pinned;
} }
function hasSource(): bool
{
return $this->getRecord()->source != NULL;
}
function getSource(bool $format = false)
{
$orig_source = $this->getRecord()->source;
if(!str_contains($orig_source, "https://") && !str_contains($orig_source, "http://"))
$orig_source = "https://" . $orig_source;
if(!$format)
return $orig_source;
return $this->formatLinks($orig_source);
}
function setSource(string $source)
{
$result = check_copyright_link($source);
$this->stateChanges("source", $source);
}
function getVkApiCopyright(): object
{
return (object)[
'id' => 0,
'link' => $this->getSource(false),
'name' => $this->getSource(false),
'type' => 'link',
];
}
function isAd(): bool function isAd(): bool
{ {
@ -226,16 +260,22 @@ class Post extends Postable
$this->save(); $this->save();
} }
function canBePinnedBy(User $user): bool function canBePinnedBy(User $user = NULL): bool
{ {
if(!$user)
return false;
if($this->getTargetWall() < 0) if($this->getTargetWall() < 0)
return (new Clubs)->get(abs($this->getTargetWall()))->canBeModifiedBy($user); return (new Clubs)->get(abs($this->getTargetWall()))->canBeModifiedBy($user);
return $this->getTargetWall() === $user->getId(); return $this->getTargetWall() === $user->getId();
} }
function canBeDeletedBy(User $user): bool function canBeDeletedBy(User $user = NULL): bool
{ {
if(!$user)
return false;
if($this->getTargetWall() < 0 && !$this->getWallOwner()->canBeModifiedBy($user) && $this->getWallOwner()->getWallType() != 1 && $this->getSuggestionType() == 0) if($this->getTargetWall() < 0 && !$this->getWallOwner()->canBeModifiedBy($user) && $this->getWallOwner()->getWallType() != 1 && $this->getSuggestionType() == 0)
return false; return false;

View file

@ -38,8 +38,19 @@ trait TRichText
$href = str_replace("#", "&num;", $matches[1]); $href = str_replace("#", "&num;", $matches[1]);
$href = rawurlencode(str_replace(";", "&#59;", $href)); $href = rawurlencode(str_replace(";", "&#59;", $href));
$link = str_replace("#", "&num;", $matches[3]); $link = str_replace("#", "&num;", $matches[3]);
# this string breaks ampersands
$link = str_replace(";", "&#59;", $link); $link = str_replace(";", "&#59;", $link);
$rel = $this->isAd() ? "sponsored" : "ugc"; $rel = $this->isAd() ? "sponsored" : "ugc";
$server_domain = str_replace(':' . $_SERVER['SERVER_PORT'], '', $_SERVER['HTTP_HOST']);
if(str_contains($link, $server_domain)) {
$replaced_link = str_replace(':' . $_SERVER['SERVER_PORT'], '', $link);
$replaced_link = str_replace($server_domain, '', $replaced_link);
return "<a href='$replaced_link' rel='$rel'>$link</a>" . htmlentities($matches[4]);
}
$link = htmlentities(urldecode($link));
return "<a href='/away.php?to=$href' rel='$rel' target='_blank'>$link</a>" . htmlentities($matches[4]); return "<a href='/away.php?to=$href' rel='$rel' target='_blank'>$link</a>" . htmlentities($matches[4]);
}), }),

View file

@ -3,6 +3,7 @@ namespace openvk\Web\Models\Repositories;
use Chandler\Database\DatabaseConnection as DB; use Chandler\Database\DatabaseConnection as DB;
use Nette\Database\Table\{ActiveRow, Selection}; use Nette\Database\Table\{ActiveRow, Selection};
use openvk\Web\Models\Entities\BannedLink; use openvk\Web\Models\Entities\BannedLink;
use function Symfony\Component\Translation\t;
class BannedLinks class BannedLinks
{ {
@ -43,7 +44,7 @@ class BannedLinks
function isDomainBanned(string $domain): bool function isDomainBanned(string $domain): bool
{ {
return sizeof($this->bannedLinks->where(["link" => $domain, "regexp_rule" => ""])) > 0; return sizeof($this->bannedLinks->where(["domain" => $domain, "regexp_rule" => ""])) > 0;
} }
function genLinks($rules): \Traversable function genLinks($rules): \Traversable
@ -57,12 +58,14 @@ class BannedLinks
foreach($links as $link) foreach($links as $link)
if (preg_match($link->getRegexpRule(), $uri)) if (preg_match($link->getRegexpRule(), $uri))
yield $link->getId(); yield $link->getId();
else if ($this->isDomainBanned($link->getDomain()))
yield $link->getId();
} }
function check(string $url): ?array function check(string $url): ?array
{ {
$uri = strstr(str_replace(["https://", "http://"], "", $url), "/", true); $uri = str_replace(["https://", "http://"], "", $url);
$domain = str_replace("www.", "", $uri); $domain = explode("/", str_replace("www.", "", $uri))[0];
$rules = $this->getByDomain($domain); $rules = $this->getByDomain($domain);
if (is_null($rules)) if (is_null($rules))

View file

@ -481,7 +481,7 @@ final class AdminPresenter extends OpenVKPresenter
if ($link) { if ($link) {
$link->setDomain($new_domain ?? $this->postParam("link")); $link->setDomain($new_domain ?? $this->postParam("link"));
$link->setReason($new_reason); $link->setReason($new_reason);
$link->setRegexp_rule($this->postParam("regexp")); $link->setRegexp_rule(mb_strlen(trim($this->postParam("regexp"))) > 0 ? $this->postParam("regexp") : "");
$link->save(); $link->save();
} else { } else {
if (!$new_domain) if (!$new_domain)
@ -490,7 +490,7 @@ final class AdminPresenter extends OpenVKPresenter
$link = new BannedLink; $link = new BannedLink;
$link->setDomain($new_domain); $link->setDomain($new_domain);
$link->setReason($new_reason); $link->setReason($new_reason);
$link->setRegexp_rule($this->postParam("regexp")); $link->setRegexp_rule(mb_strlen(trim($this->postParam("regexp"))) > 0 ? $this->postParam("regexp") : "");
$link->setInitiator($this->user->identity->getId()); $link->setInitiator($this->user->identity->getId());
$link->save(); $link->save();

View file

@ -7,7 +7,7 @@ final class AwayPresenter extends OpenVKPresenter
{ {
function renderAway(): void function renderAway(): void
{ {
$checkBanEntries = (new BannedLinks)->check($this->queryParam("to") . "/"); $checkBanEntries = (new BannedLinks)->check($this->queryParam("to"));
if (OPENVK_ROOT_CONF["openvk"]["preferences"]["susLinks"]["warnings"]) if (OPENVK_ROOT_CONF["openvk"]["preferences"]["susLinks"]["warnings"])
if (sizeof($checkBanEntries) > 0) if (sizeof($checkBanEntries) > 0)
$this->pass("openvk!Away->view", $checkBanEntries[0]); $this->pass("openvk!Away->view", $checkBanEntries[0]);

View file

@ -367,6 +367,12 @@ final class WallPresenter extends OpenVKPresenter
$post->setFlags($flags); $post->setFlags($flags);
$post->setNsfw($this->postParam("nsfw") === "on"); $post->setNsfw($this->postParam("nsfw") === "on");
if(!empty($this->postParam("source")) && $this->postParam("source") != 'none') {
try {
$post->setSource($this->postParam("source"));
} catch(\Throwable) {}
}
if($wall < 0 && !$wallOwner->canBeModifiedBy($this->user->identity) && $wallOwner->getWallType() == 2) if($wall < 0 && !$wallOwner->canBeModifiedBy($this->user->identity) && $wallOwner->getWallType() == 2)
$post->setSuggested(1); $post->setSuggested(1);

View file

@ -18,7 +18,7 @@
{else} {else}
<a href="{$owner->getURL()}">{$owner->getCanonicalName()}</a> <a href="{$owner->getURL()}">{$owner->getCanonicalName()}</a>
» »
<a href="/playlists{$ownerId}">{_playlists}</a> <a href="/playlists{$owner->getRealId()}">{_playlists}</a>
» »
<a href="/playlist{$playlist->getPrettyId()}">{_playlist}</a> <a href="/playlist{$playlist->getPrettyId()}">{_playlist}</a>
{/if} {/if}

View file

@ -17,7 +17,7 @@
<a n:if="!$isMy" n:attr="id => $mode === 'list' ? 'used' : 'ki'" href="/audios{$ownerId}">{if $ownerId > 0}{_music_user}{else}{_music_club}{/if}</a> <a n:if="!$isMy" n:attr="id => $mode === 'list' ? 'used' : 'ki'" href="/audios{$ownerId}">{if $ownerId > 0}{_music_user}{else}{_music_club}{/if}</a>
<a href="/player/upload?gid={abs($ownerId)}" n:if="isset($thisUser) && isset($club) && $club->canUploadAudio($thisUser)">{_upload_audio}</a> <a href="/player/upload?gid={abs($ownerId)}" n:if="isset($thisUser) && isset($club) && $club->canUploadAudio($thisUser)">{_upload_audio}</a>
<a n:attr="id => $mode === 'playlists' && $ownerId != $thisUser->getId() ? 'used' : 'ki'" href="/playlists{$ownerId}" n:if="isset($thisUser) && isset($ownerId) && !$isMy">{if $ownerId > 0}{_playlists_user}{else}{_playlists_club}{/if}</a> <a n:attr="id => $mode === 'playlists' && $ownerId != $thisUser->getId() ? 'used' : 'ki'" class='noOverflow' href="/playlists{$ownerId}" n:if="isset($thisUser) && isset($ownerId) && !$isMy">{if $ownerId > 0}{_playlists_user}{else}{_playlists_club}{/if}</a>
<a href="/audios/newPlaylist{if $isMyClub}?gid={abs($ownerId)}{/if}" n:if="isset($thisUser) && $isMyClub">{_new_playlist}</a> <a href="/audios/newPlaylist{if $isMyClub}?gid={abs($ownerId)}{/if}" n:if="isset($thisUser) && $isMyClub">{_new_playlist}</a>
{/if} {/if}
</div> </div>

View file

@ -202,7 +202,7 @@
{if isset($thisUser) && $user->getId() === $thisUser->getId() && sizeof($completeness->unfilled) > 0} {if isset($thisUser) && $user->getId() === $thisUser->getId() && sizeof($completeness->unfilled) > 0}
<br/> <br/>
<a n:if="in_array('interests', $completeness->unfilled)" href="/edit"> <a n:if="in_array('interests', $completeness->unfilled)" href="/edit?act=interests">
<img src="/assets/packages/static/openvk/img/icon1.gif" /> <img src="/assets/packages/static/openvk/img/icon1.gif" />
{_interests} (+20%) {_interests} (+20%)
</a> </a>

View file

@ -18,7 +18,7 @@
</div> </div>
<div n:class="postFeedWrapper, $thisUser->hasMicroblogEnabled() ? postFeedWrapperMicroblog"> <div n:class="postFeedWrapper, $thisUser->hasMicroblogEnabled() ? postFeedWrapperMicroblog">
{include "../components/textArea.xml", route => "/wall" . $thisUser->getId() . "/makePost", graffiti => true, polls => true, notes => true} {include "../components/textArea.xml", route => "/wall" . $thisUser->getId() . "/makePost", graffiti => true, polls => true, notes => true, hasSource => true}
</div> </div>
{foreach $posts as $post} {foreach $posts as $post}

View file

@ -28,7 +28,7 @@
</div> </div>
<div n:if="$canPost && $type == 'all'" class="content_subtitle"> <div n:if="$canPost && $type == 'all'" class="content_subtitle">
{include "../components/textArea.xml", route => "/wall$owner/makePost"} {include "../components/textArea.xml", route => "/wall$owner/makePost", hasSource => true}
</div> </div>
<div class="content"> <div class="content">

View file

@ -1,9 +1,11 @@
{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 $likesCount = $comment->getLikesCount()}
{var $target = $comment->getTarget()}
{var $postId = $target instanceof \openvk\Web\Models\Entities\Post ? $target->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="{$author instanceof $Club}" n:attr="data-post-id => $postId">
<tbody> <tbody>
<tr> <tr>
<td width="30" valign="top"> <td width="30" valign="top">
@ -40,8 +42,8 @@
<span n:if="$comment->getEditTime()" class="edited editedMark">({_edited_short})</span> <span n:if="$comment->getEditTime()" class="edited editedMark">({_edited_short})</span>
</a> </a>
{if !$timeOnly} {if !$timeOnly}
&nbsp;|
{if $comment->canBeDeletedBy($thisUser)} {if $comment->canBeDeletedBy($thisUser)}
|
<a href="/comment{$comment->getId()}/delete">{_delete}</a> <a href="/comment{$comment->getId()}/delete">{_delete}</a>
{/if} {/if}
{if $comment->canBeEditedBy($thisUser)} {if $comment->canBeEditedBy($thisUser)}
@ -60,7 +62,7 @@
<div style="float: right; font-size: .7rem;"> <div style="float: right; font-size: .7rem;">
<a class="post-like-button" href="/comment{$comment->getId()}/like?hash={rawurlencode($csrfToken)}"> <a class="post-like-button" href="/comment{$comment->getId()}/like?hash={rawurlencode($csrfToken)}">
<div class="heart" style="{if $comment->hasLikeFrom($thisUser)}opacity: 1;{else}opacity: 0.4;{/if}"></div> <div class="heart" style="{if $comment->hasLikeFrom($thisUser)}opacity: 1;{else}opacity: 0.4;{/if}"></div>
<span class="likeCnt">{if $comment->getLikesCount() > 0}{$comment->getLikesCount()}{/if}</span> <span class="likeCnt">{if $likesCount > 0}{$likesCount}{/if}</span>
</a> </a>
</div> </div>
{/if} {/if}
@ -101,4 +103,4 @@
Function.noop Function.noop
]); ]);
} }
</script> </script>

View file

@ -3,6 +3,11 @@
{var $commentsCount = $post->getCommentsCount()} {var $commentsCount = $post->getCommentsCount()}
{var $platform = $post->getPlatform()} {var $platform = $post->getPlatform()}
{var $platformDetails = $post->getPlatformDetails()} {var $platformDetails = $post->getPlatformDetails()}
{var $likesCount = $post->getLikesCount()}
{var $repostsCount = $post->getRepostCount()}
{var $canBePinned = $post->canBePinnedBy($thisUser ?? NULL)}
{var $canBeDeleted = $post->canBeDeletedBy($thisUser)}
{var $wallOwner = $post->getWallOwner()}
{if $post->isDeactivationMessage() && $post->getText()} {if $post->isDeactivationMessage() && $post->getText()}
{var $deac = "post_deact"} {var $deac = "post_deact"}
{else} {else}
@ -30,7 +35,6 @@
{$post->isUpdateAvatarMessage() && !$post->isPostedOnBehalfOfGroup() ? ($author->isFemale() ? tr("upd_f") : ($author->isNeutral() ? tr("upd_n") : tr("upd_m")))} {$post->isUpdateAvatarMessage() && !$post->isPostedOnBehalfOfGroup() ? ($author->isFemale() ? tr("upd_f") : ($author->isNeutral() ? tr("upd_n") : tr("upd_m")))}
{$post->isUpdateAvatarMessage() && $post->isPostedOnBehalfOfGroup() ? tr("upd_g") : ""} {$post->isUpdateAvatarMessage() && $post->isPostedOnBehalfOfGroup() ? tr("upd_g") : ""}
{if ($onWallOf ?? false) &&!$post->isPostedOnBehalfOfGroup() && $post->getOwnerPost() !== $post->getTargetWall()} {if ($onWallOf ?? false) &&!$post->isPostedOnBehalfOfGroup() && $post->getOwnerPost() !== $post->getTargetWall()}
{var $wallOwner = $post->getWallOwner()}
<a href="{$wallOwner->getURL()}" class="mention" data-mention-ref="{$post->getTargetWall()}"> <a href="{$wallOwner->getURL()}" class="mention" data-mention-ref="{$post->getTargetWall()}">
<b> <b>
{if isset($thisUser) && $thisUser->getId() === $post->getTargetWall()} {if isset($thisUser) && $thisUser->getId() === $post->getTargetWall()}
@ -53,9 +57,9 @@
<span n:if="$post->isPinned()" class="nobold">{_pinned}</span> <span n:if="$post->isPinned()" class="nobold">{_pinned}</span>
<a n:if="$post->canBeDeletedBy($thisUser) && !($forceNoDeleteLink ?? false) && $compact == false" class="delete" href="/wall{$post->getPrettyId()}/delete"></a> <a n:if="$canBeDeleted && !($forceNoDeleteLink ?? false) && $compact == false" class="delete" href="/wall{$post->getPrettyId()}/delete"></a>
{if $post->canBePinnedBy($thisUser) && !($forceNoPinLink ?? false) && $compact == false} {if $canBePinned && !($forceNoPinLink ?? false) && $compact == false}
{if $post->isPinned()} {if $post->isPinned()}
<a class="pin" href="/wall{$post->getPrettyId()}/pin?act=unpin&hash={rawurlencode($csrfToken)}"></a> <a class="pin" href="/wall{$post->getPrettyId()}/pin?act=unpin&hash={rawurlencode($csrfToken)}"></a>
{else} {else}
@ -67,7 +71,7 @@
<a class="edit" id="editPost" <a class="edit" id="editPost"
data-id="{$post->getId()}" data-id="{$post->getId()}"
data-nsfw="{(int)$post->isExplicit()}" data-nsfw="{(int)$post->isExplicit()}"
{if $post->getTargetWall() < 0 && $post->getWallOwner()->canBeModifiedBy($thisUser)}data-fromgroup="{(int)$post->isPostedOnBehalfOfGroup()}"{/if}></a> {if $post->getTargetWall() < 0 && $wallOwner->canBeModifiedBy($thisUser)}data-fromgroup="{(int)$post->isPostedOnBehalfOfGroup()}"{/if}></a>
{/if} {/if}
</div> </div>
<div class="post-content" id="{$post->getPrettyId()}"> <div class="post-content" id="{$post->getPrettyId()}">
@ -95,6 +99,9 @@
<br/> <br/>
&nbsp;! {_post_is_ad} &nbsp;! {_post_is_ad}
</div> </div>
<div n:if="$post->hasSource()" class="sourceDiv">
<span>{_source}: {$post->getSource(true)|noescape}</span>
</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>
@ -121,14 +128,14 @@
<div class="like_wrap"> <div class="like_wrap">
<a n:if="!($forceNoShareLink ?? false)" id="reposts{$post->getPrettyId()}" class="post-share-button" href="javascript:repostPost('{$post->getPrettyId()}', '{rawurlencode($csrfToken)}')"> <a n:if="!($forceNoShareLink ?? false)" id="reposts{$post->getPrettyId()}" class="post-share-button" href="javascript:repostPost('{$post->getPrettyId()}', '{rawurlencode($csrfToken)}')">
<div class="repost-icon" style="opacity: 0.4;"></div> <div class="repost-icon" style="opacity: 0.4;"></div>
<span class="likeCnt" id="repostsCount{$post->getPrettyId()}">{if $post->getRepostCount() > 0}{$post->getRepostCount()}{/if}</span> <span class="likeCnt" id="repostsCount{$post->getPrettyId()}">{if $repostsCount > 0}{$repostsCount}{/if}</span>
</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="{$likesCount}">
<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 $likesCount > 0}{$likesCount}{/if}</span>
</a> </a>
{/if} {/if}
</div> </div>
@ -145,7 +152,7 @@
{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>
<div n:if="$suggestion && $post->canBePinnedBy($thisUser ?? NULL)" class="suggestionControls"> <div n:if="$suggestion && $canBePinned" class="suggestionControls">
<input type="button" class="button" id="publish_post" data-id="{$post->getId()}" value="{_publish_suggested}"> <input type="button" class="button" id="publish_post" data-id="{$post->getId()}" value="{_publish_suggested}">
<input type="button" class="button" id="decline_post" data-id="{$post->getId()}" value="{_decline_suggested}"> <input type="button" class="button" id="decline_post" data-id="{$post->getId()}" value="{_decline_suggested}">
</div> </div>

View file

@ -1,6 +1,12 @@
{var $author = $post->getOwner()} {var $author = $post->getOwner()}
{var $platform = $post->getPlatform()} {var $platform = $post->getPlatform()}
{var $platformDetails = $post->getPlatformDetails()} {var $platformDetails = $post->getPlatformDetails()}
{var $wallOwner = $post->getWallOwner()}
{var $likesCount = $post->getLikesCount()}
{var $repostsCount = $post->getRepostCount()}
{var $commentsCount = $post->getCommentsCount()}
{var $canBePinned = $post->canBePinnedBy($thisUser ?? NULL)}
{var $canBeDeleted = $post->canBeDeletedBy($thisUser)}
{if $post->isDeactivationMessage() && $post->getText()} {if $post->isDeactivationMessage() && $post->getText()}
{var $deac = "post_deact"} {var $deac = "post_deact"}
{else} {else}
@ -40,7 +46,6 @@
{/if} {/if}
{/if} {/if}
{if ($onWallOf ?? false) &&!$post->isPostedOnBehalfOfGroup() && $post->getOwnerPost() !== $post->getTargetWall()} {if ($onWallOf ?? false) &&!$post->isPostedOnBehalfOfGroup() && $post->getOwnerPost() !== $post->getTargetWall()}
{var $wallOwner = $post->getWallOwner()}
<a href="{$wallOwner->getURL()}" class="mention" data-mention-ref="{$post->getTargetWall()}"> <a href="{$wallOwner->getURL()}" class="mention" data-mention-ref="{$post->getTargetWall()}">
<b> <b>
{if isset($thisUser) && $thisUser->getId() === $post->getTargetWall()} {if isset($thisUser) && $thisUser->getId() === $post->getTargetWall()}
@ -85,7 +90,7 @@
</div> </div>
</div> </div>
</div> </div>
<div n:if="$suggestion && $post->canBePinnedBy($thisUser ?? NULL)" class="suggestionControls" style="margin-bottom: 7px;"> <div n:if="$suggestion && $canBePinned" class="suggestionControls" style="margin-bottom: 7px;">
<input type="button" class="button" id="publish_post" data-id="{$post->getId()}" value="{_publish_suggested}"> <input type="button" class="button" id="publish_post" data-id="{$post->getId()}" value="{_publish_suggested}">
<input type="button" class="button" id="decline_post" data-id="{$post->getId()}" value="{_decline_suggested}"> <input type="button" class="button" id="decline_post" data-id="{$post->getId()}" value="{_decline_suggested}">
</div> </div>
@ -93,6 +98,9 @@
<br/> <br/>
&nbsp;! {_post_is_ad} &nbsp;! {_post_is_ad}
</div> </div>
<div n:if="$post->hasSource()" class="sourceDiv">
<span>{_source}: {$post->getSource(true)|noescape}</span>
</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>
@ -113,14 +121,14 @@
<a id="editPost" <a id="editPost"
data-id="{$post->getId()}" data-id="{$post->getId()}"
data-nsfw="{(int)$post->isExplicit()}" data-nsfw="{(int)$post->isExplicit()}"
{if $post->getTargetWall() < 0 && $post->getWallOwner()->canBeModifiedBy($thisUser)}data-fromgroup="{(int)$post->isPostedOnBehalfOfGroup()}"{/if}>{_edit}</a> &nbsp;|&nbsp; {if $post->getTargetWall() < 0 && $wallOwner->canBeModifiedBy($thisUser)}data-fromgroup="{(int)$post->isPostedOnBehalfOfGroup()}"{/if}>{_edit}</a> &nbsp;|&nbsp;
{/if} {/if}
{if !($forceNoDeleteLink ?? false) && $post->canBeDeletedBy($thisUser)} {if !($forceNoDeleteLink ?? false) && $canBeDeleted}
<a href="/wall{$post->getPrettyId()}/delete">{_delete}</a> &nbsp;|&nbsp; <a href="/wall{$post->getPrettyId()}/delete">{_delete}</a> &nbsp;|&nbsp;
{/if} {/if}
{if !($forceNoPinLink ?? false) && $post->canBePinnedBy($thisUser)} {if !($forceNoPinLink ?? false) && $canBePinned}
{if $post->isPinned()} {if $post->isPinned()}
<a href="/wall{$post->getPrettyId()}/pin?act=unpin&hash={rawurlencode($csrfToken)}">{_unpin}</a> <a href="/wall{$post->getPrettyId()}/pin?act=unpin&hash={rawurlencode($csrfToken)}">{_unpin}</a>
{else} {else}
@ -131,8 +139,8 @@
<a n:if="!($forceNoCommentsLink ?? false)" href="/wall{$post->getPrettyId()}#comments"> <a n:if="!($forceNoCommentsLink ?? false)" href="/wall{$post->getPrettyId()}#comments">
{_comments} {_comments}
{if $post->getCommentsCount() > 0} {if $commentsCount > 0}
(<b>{$post->getCommentsCount()}</b>) (<b>{$commentsCount}</b>)
{/if} {/if}
</a> </a>
@ -142,22 +150,22 @@
<a n:if="!($forceNoShareLink ?? false)" id="reposts{$post->getPrettyId()}" class="post-share-button" {ifset $thisUser} href="javascript:repostPost('{$post->getPrettyId()}', '{rawurlencode($csrfToken)}')"{/ifset}> <a n:if="!($forceNoShareLink ?? false)" id="reposts{$post->getPrettyId()}" class="post-share-button" {ifset $thisUser} href="javascript:repostPost('{$post->getPrettyId()}', '{rawurlencode($csrfToken)}')"{/ifset}>
{_share} {_share}
{if $post->getRepostCount() > 0} {if $repostsCount > 0}
(<b id="repostsCount{$post->getPrettyId()}">{$post->getRepostCount()}</b>) (<b id="repostsCount{$post->getPrettyId()}">{$repostsCount}</b>)
{/if} {/if}
</a> </a>
<div n:if="!($forceNoLike ?? false)" class="like_wrap"> <div n:if="!($forceNoLike ?? false)" class="like_wrap">
{ifset $thisUser} {ifset $thisUser}
{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="{$likesCount}">
<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 $likesCount > 0}{$likesCount}{/if}</span>
</a> </a>
{else} {else}
<a n:if="$post->getLikesCount() > 0" class="post-like-button"> <a n:if="$likesCount > 0" class="post-like-button">
<div class="heart"></div> <div class="heart"></div>
<span class="likeCnt">{$post->getLikesCount()}</span> <span class="likeCnt">{$likesCount}</span>
</a> </a>
{/ifset} {/ifset}
</div> </div>

View file

@ -18,14 +18,15 @@
<div class="post-has-poll"> <div class="post-has-poll">
{_poll} {_poll}
</div> </div>
<div class="post-has-note"> <div class="post-has-note"></div>
</div>
<div class="post-has-videos"></div> <div class="post-has-videos"></div>
<div class="post-has-audios"></div> <div class="post-has-audios"></div>
<div class="post-source"></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)}
<script> <script>
@ -66,6 +67,7 @@
<input type="hidden" name="audios" value="" /> <input type="hidden" name="audios" value="" />
<input type="hidden" name="poll" value="none" /> <input type="hidden" name="poll" value="none" />
<input type="hidden" id="note" name="note" value="none" /> <input type="hidden" id="note" name="note" value="none" />
<input type="hidden" id="source" name="source" value="none" />
<input type="hidden" name="type" value="1" /> <input type="hidden" name="type" value="1" />
<input type="hidden" name="hash" value="{$csrfToken}" /> <input type="hidden" name="hash" value="{$csrfToken}" />
<br/> <br/>
@ -91,10 +93,6 @@
<img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/mimetypes/audio-ac3.png" /> <img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/mimetypes/audio-ac3.png" />
{_audio} {_audio}
</a> </a>
<a n:if="$notes ?? false" href="javascript:attachNote({$textAreaId})">
<img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/mimetypes/application-x-srt.png" />
{_note}
</a>
<a n:if="$graffiti ?? false" href="javascript:initGraffiti({$textAreaId});"> <a n:if="$graffiti ?? false" href="javascript:initGraffiti({$textAreaId});">
<img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/actions/draw-brush.png" /> <img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/actions/draw-brush.png" />
{_graffiti} {_graffiti}
@ -103,6 +101,10 @@
<img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/actions/office-chart-bar-stacked.png" /> <img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/actions/office-chart-bar-stacked.png" />
{_poll} {_poll}
</a> </a>
<a n:if="$hasSource ?? false" id='__sourceAttacher'>
<img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/actions/insert-link.png" />
{_source}
</a>
</div> </div>
</div> </div>
</div> </div>

View file

@ -10,7 +10,7 @@
<div class="insertThere" id="postz"></div> <div class="insertThere" id="postz"></div>
<div id="underHeader"> <div id="underHeader">
<div n:if="$canPost" class="content_subtitle"> <div n:if="$canPost" class="content_subtitle">
{include "../components/textArea.xml", route => "/wall$owner/makePost", graffiti => true, polls => true, notes => true} {include "../components/textArea.xml", route => "/wall$owner/makePost", graffiti => true, polls => true, notes => true, hasSource => true}
</div> </div>
<div class="content"> <div class="content">

View file

@ -70,7 +70,7 @@ class Makima
$result->colSizes = [1]; $result->colSizes = [1];
$result->rowSizes = [1, 1]; $result->rowSizes = [1, 1];
$result->width = ceil($maxWidth); $result->width = ceil($maxWidth);
$result->height = $computedHeight; $result->height = $computedHeight * 2;
$result->tiles = [new ThumbTile(1, 1, $maxWidth, $computedHeight), new ThumbTile(1, 1, $maxWidth, $computedHeight)]; $result->tiles = [new ThumbTile(1, 1, $maxWidth, $computedHeight), new ThumbTile(1, 1, $maxWidth, $computedHeight)];
} else if( } else if(
$orients == [Makima::ORIENT_WIDE, Makima::ORIENT_WIDE] $orients == [Makima::ORIENT_WIDE, Makima::ORIENT_WIDE]

View file

@ -9,7 +9,7 @@
} }
.musicIcon { .musicIcon {
background-image: url('/assets/packages/static/openvk/img/audios_controls.png'); background-image: url('/assets/packages/static/openvk/img/audios_controls.png?v=2');
background-repeat: no-repeat; background-repeat: no-repeat;
cursor: pointer; cursor: pointer;
} }
@ -185,6 +185,7 @@
width: 81%; width: 81%;
height: 13px; height: 13px;
display: inline-block; display: inline-block;
line-height: 14px;
} }
.bigPlayer .paddingLayer .trackInfo .timer span { .bigPlayer .paddingLayer .trackInfo .timer span {
@ -345,6 +346,7 @@
.audioEntry .status .mediaInfo { .audioEntry .status .mediaInfo {
cursor: pointer; cursor: pointer;
display: flex; display: flex;
line-height: 14px;
width: 100%; width: 100%;
} }

View file

@ -44,7 +44,7 @@
._add_image::before { ._add_image::before {
margin-top: 2px; margin-top: 2px;
content: ' '; content: ' ';
background: url('/assets/packages/static/openvk/img/upload.png'); background: url('/assets/packages/static/openvk/img/upload.png?v=2');
width: 10px; width: 10px;
height: 10px; height: 10px;
display: inline-block; display: inline-block;
@ -65,7 +65,7 @@
.avatarDelete::before { .avatarDelete::before {
content: ' '; content: ' ';
background: url('/assets/packages/static/openvk/img/upload.png'); background: url('/assets/packages/static/openvk/img/upload.png?v=2');
background-position: -10px 2px; background-position: -10px 2px;
background-repeat: no-repeat; background-repeat: no-repeat;
width: 12px; width: 12px;

View file

@ -1454,6 +1454,24 @@ body.scrolled .toTop:hover {
color: #3c3c3c; color: #3c3c3c;
} }
.post-source #remove_source_button {
display: inline-block;
background-repeat: no-repeat;
background: url('/assets/packages/static/openvk/img/arrows.png?v=2');
margin-bottom: -2px;
background-position: -18px 0px;
height: 11px;
width: 11px;
opacity: 0.6;
transition-duration: 0.3s;
cursor: pointer;
}
.post-source #remove_source_button:hover {
opacity: 0.8;
}
.post-upload::before, .post-has-poll::before, .post-has-note::before { .post-upload::before, .post-has-poll::before, .post-has-note::before {
content: " "; content: " ";
width: 8px; width: 8px;
@ -3019,6 +3037,26 @@ body.article .floating_sidebar, body.article .page_content {
font-size: 12px; font-size: 12px;
} }
.post .sourceDiv {
margin-top: 3px;
margin-left: 4px;
}
.post .sourceDiv span {
color: grey;
font-size: 10px;
}
.post .sourceDiv a:hover {
text-decoration: underline;
}
#source_flex_kunteynir {
display: flex;
flex-direction: column;
gap: 22px;
}
.sugglist { .sugglist {
padding-bottom: 5px; padding-bottom: 5px;
padding-top: 5px; padding-top: 5px;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 219 B

After

Width:  |  Height:  |  Size: 316 B

View file

@ -66,16 +66,16 @@ u(`#search_box input[type='search']`).on('input', async (e) => {
switch(section) { switch(section) {
case 'users': case 'users':
results = await fetch(`/method/users.search?auth_mechanism=roaming&q=${query}&count=10&sort=4&fields=photo_50,status,nickname`) results = await fetch(`/method/users.search?auth_mechanism=roaming&q=${encodeURIComponent(query)}&count=10&sort=4&fields=photo_50,status,nickname`)
break break
case 'groups': case 'groups':
results = await fetch(`/method/groups.search?auth_mechanism=roaming&q=${query}&count=10&sort=4&fields=photo_50,description`) results = await fetch(`/method/groups.search?auth_mechanism=roaming&q=${encodeURIComponent(query)}&count=10&sort=4&fields=photo_50,description`)
break break
case 'videos': case 'videos':
results = await fetch(`/method/video.search?auth_mechanism=roaming&q=${query}&count=10&sort=4&extended=1`) results = await fetch(`/method/video.search?auth_mechanism=roaming&q=${encodeURIComponent(query)}&count=10&sort=4&extended=1`)
break break
case 'audios_playlists': case 'audios_playlists':
results = await fetch(`/method/audio.searchAlbums?auth_mechanism=roaming&query=${query}&limit=10`) results = await fetch(`/method/audio.searchAlbums?auth_mechanism=roaming&query=${encodeURIComponent(query)}&limit=10`)
break break
} }

View file

@ -1145,7 +1145,7 @@ $(document).on("click", "#editPost", (e) => {
} }
post.querySelector(".post-avatar").setAttribute("src", result.author.avatar) post.querySelector(".post-avatar").setAttribute("src", result.author.avatar)
post.querySelector(".post-author-name").innerHTML = result.author.name post.querySelector(".post-author-name").innerHTML = result.author.name.escapeHtml()
post.querySelector(".really_text").setAttribute("data-text", result.new_text) post.querySelector(".really_text").setAttribute("data-text", result.new_text)
} else { } else {
MessageBox(tr("error"), result.error, [tr("ok")], [Function.noop]) MessageBox(tr("error"), result.error, [tr("ok")], [Function.noop])
@ -1626,7 +1626,7 @@ $(document).on("click", ".avatarDelete", (e) => {
u("body").removeClass("dimmed"); u("body").removeClass("dimmed");
document.querySelector("html").style.overflowY = "scroll" document.querySelector("html").style.overflowY = "scroll"
u(".ovk-diag-cont").remove(); u(".ovk-diag-cont").remove()
document.querySelector("#bigAvatar").src = response.url document.querySelector("#bigAvatar").src = response.url
document.querySelector("#bigAvatar").parentNode.href = response.new_photo ? ("/photo" + response.new_photo) : "javascript:void(0)" document.querySelector("#bigAvatar").parentNode.href = response.new_photo ? ("/photo" + response.new_photo) : "javascript:void(0)"
@ -1643,3 +1643,77 @@ $(document).on("click", ".avatarDelete", (e) => {
}), }),
]); ]);
}) })
u(document).on('click', '#__sourceAttacher', (e) => {
MessageBox(tr('add_source'), `
<div id='source_flex_kunteynir'>
<span>${tr('set_source_tip')}</span>
<!-- давай, копируй ссылку и переходи по ней -->
<input type='text' maxlength='400' placeholder='https://www.youtube.com/watch?v=lkWuk_nzzVA'>
</div>
`, [tr('cancel')], [
() => {Function.noop}
])
__removeDialog = () => {
u("body").removeClass("dimmed");
document.querySelector("html").style.overflowY = "scroll"
u(".ovk-diag-cont").remove()
}
u('.ovk-diag-action').append(`
<button class='button' id='__setsrcbutton'>${tr('set_source')}</button>
`)
u('.ovk-diag-action #__setsrcbutton').on('click', async (ev) => {
// Consts
const _u_target = u(e.target)
const nearest_textarea = _u_target.closest('#write')
const source_output = nearest_textarea.find(`input[name='source']`)
const source_input = u(`#source_flex_kunteynir input[type='text']`)
const source_value = source_input.nodes[0].value ?? ''
if(source_value.length < 1) {
return
}
ev.target.classList.add('lagged')
// Checking link
const __checkCopyrightLinkRes = await fetch(`/method/wall.checkCopyrightLink?auth_mechanism=roaming&link=${encodeURIComponent(source_value)}`)
const checkCopyrightLink = await __checkCopyrightLinkRes.json()
// todo переписать блять мессенджбоксы чтоб они классами были
if(checkCopyrightLink.error_code) {
__removeDialog()
switch(checkCopyrightLink.error_code) {
default:
case 3102:
fastError(tr('error_adding_source_regex'))
return
case 3103:
fastError(tr('error_adding_source_long'))
return
case 3104:
fastError(tr('error_adding_source_sus'))
return
}
}
// Making indicator
__removeDialog()
source_output.attr('value', source_value)
nearest_textarea.find('.post-source').html(`
<span>${tr('source')}: <a target='_blank' href='${source_value.escapeHtml()}'>${ovk_proc_strtr(source_value.escapeHtml(), 50)}</a></span>
<div id='remove_source_button'></div>
`)
nearest_textarea.find('.post-source #remove_source_button').on('click', () => {
nearest_textarea.find('.post-source').html('')
source_output.attr('value', 'none')
})
})
u('.ovk-diag-body').attr('style', `padding:8px;`)
u('.ovk-diag-cont').attr('style', 'width: 325px;')
u('#source_flex_kunteynir input').nodes[0].focus()
})

View file

@ -286,6 +286,31 @@ function ovk_scheme(bool $with_slashes = false): string
return $scheme; return $scheme;
} }
function check_copyright_link(string $link = ''): bool
{
if(!str_contains($link, "https://") && !str_contains($link, "http://"))
$link = "https://" . $link;
# Existability
if(is_null($link) || empty($link))
throw new \InvalidArgumentException("Empty link");
# Length
if(iconv_strlen($link) < 2 || iconv_strlen($link) > 400)
throw new \LengthException("Link is too long");
# Match URL regex
# stolen from http://urlregex.com/
if (!preg_match("%^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@|\d{1,3}(?:\.\d{1,3}){3}|(?:(?:[a-z\d\x{00a1}-\x{ffff}]+-?)*[a-z\d\x{00a1}-\x{ffff}]+|xn--[a-z\d-]+)(?:\.(?:[a-z\d\x{00a1}-\x{ffff}]+-?)*[a-z\d\x{00a1}-\x{ffff}]+)*(?:\.(?:xn--[a-z\d-]+|[a-z\x{00a1}-\x{ffff}]{2,6})))(?::\d+)?(?:[^\s]*)?$%iu", $link))
throw new \InvalidArgumentException("Invalid link format");
$banEntries = (new openvk\Web\Models\Repositories\BannedLinks)->check($link);
if(sizeof($banEntries) > 0)
throw new \LogicException("Suspicious link");
return true;
}
return (function() { return (function() {
_ovk_check_environment(); _ovk_check_environment();
require __DIR__ . "/vendor/autoload.php"; require __DIR__ . "/vendor/autoload.php";

373
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": "0d3b0eb1916eaf088444ef637743284a", "content-hash": "987e26c5520b71fccd0cd31de00eead2",
"packages": [ "packages": [
{ {
"name": "al/emoji-detector", "name": "al/emoji-detector",
@ -197,16 +197,16 @@
}, },
{ {
"name": "chillerlan/php-settings-container", "name": "chillerlan/php-settings-container",
"version": "3.2.0", "version": "3.2.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/chillerlan/php-settings-container.git", "url": "https://github.com/chillerlan/php-settings-container.git",
"reference": "8f93648fac8e6bacac8e00a8d325eba4950295e6" "reference": "95ed3e9676a1d47cab2e3174d19b43f5dbf52681"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/chillerlan/php-settings-container/zipball/8f93648fac8e6bacac8e00a8d325eba4950295e6", "url": "https://api.github.com/repos/chillerlan/php-settings-container/zipball/95ed3e9676a1d47cab2e3174d19b43f5dbf52681",
"reference": "8f93648fac8e6bacac8e00a8d325eba4950295e6", "reference": "95ed3e9676a1d47cab2e3174d19b43f5dbf52681",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -214,15 +214,16 @@
"php": "^8.1" "php": "^8.1"
}, },
"require-dev": { "require-dev": {
"phan/phan": "^5.4",
"phpmd/phpmd": "^2.15", "phpmd/phpmd": "^2.15",
"phpstan/phpstan": "^1.11",
"phpstan/phpstan-deprecation-rules": "^1.2",
"phpunit/phpunit": "^10.5", "phpunit/phpunit": "^10.5",
"squizlabs/php_codesniffer": "^3.9" "squizlabs/php_codesniffer": "^3.10"
}, },
"type": "library", "type": "library",
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"chillerlan\\Settings\\": "src/" "chillerlan\\Settings\\": "src"
} }
}, },
"notification-url": "https://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
@ -258,7 +259,7 @@
"type": "ko_fi" "type": "ko_fi"
} }
], ],
"time": "2024-03-02T20:07:15+00:00" "time": "2024-07-16T11:13:48+00:00"
}, },
{ {
"name": "erusev/parsedown", "name": "erusev/parsedown",
@ -266,20 +267,20 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/erusev/parsedown.git", "url": "https://github.com/erusev/parsedown.git",
"reference": "1ff038273949df7d6a455352659a878f3c89b29c" "reference": "582f9f9cd12a894a0901bef1652854a3c5a1d874"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/erusev/parsedown/zipball/1ff038273949df7d6a455352659a878f3c89b29c", "url": "https://api.github.com/repos/erusev/parsedown/zipball/582f9f9cd12a894a0901bef1652854a3c5a1d874",
"reference": "1ff038273949df7d6a455352659a878f3c89b29c", "reference": "582f9f9cd12a894a0901bef1652854a3c5a1d874",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-mbstring": "*", "ext-mbstring": "*",
"php": ">=5.3.0" "php": ">=7.1"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^4.8.35" "phpunit/phpunit": "^7.5|^8.5|^9.6"
}, },
"default-branch": true, "default-branch": true,
"type": "library", "type": "library",
@ -309,7 +310,7 @@
"issues": "https://github.com/erusev/parsedown/issues", "issues": "https://github.com/erusev/parsedown/issues",
"source": "https://github.com/erusev/parsedown/tree/master" "source": "https://github.com/erusev/parsedown/tree/master"
}, },
"time": "2024-03-12T05:27:45+00:00" "time": "2024-10-12T07:06:08+00:00"
}, },
{ {
"name": "ezyang/htmlpurifier", "name": "ezyang/htmlpurifier",
@ -317,12 +318,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/ezyang/htmlpurifier.git", "url": "https://github.com/ezyang/htmlpurifier.git",
"reference": "4828fdf45a93eeeacfcbcc855f96f9a7e6b4ed44" "reference": "cb56001e54359df7ae76dc522d08845dc741621b"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/4828fdf45a93eeeacfcbcc855f96f9a7e6b4ed44", "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/cb56001e54359df7ae76dc522d08845dc741621b",
"reference": "4828fdf45a93eeeacfcbcc855f96f9a7e6b4ed44", "reference": "cb56001e54359df7ae76dc522d08845dc741621b",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -369,9 +370,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/ezyang/htmlpurifier/issues", "issues": "https://github.com/ezyang/htmlpurifier/issues",
"source": "https://github.com/ezyang/htmlpurifier/tree/master" "source": "https://github.com/ezyang/htmlpurifier/tree/v4.18.0"
}, },
"time": "2024-03-13T03:41:45+00:00" "time": "2024-11-01T03:51:45+00:00"
}, },
{ {
"name": "guzzlehttp/guzzle", "name": "guzzlehttp/guzzle",
@ -678,12 +679,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/JamesHeinrich/getID3.git", "url": "https://github.com/JamesHeinrich/getID3.git",
"reference": "143af3325ee40e77c5d041d3f674c8bdd4762dc7" "reference": "eb358a0d4943c0cc23e783f1a72141f46153c13a"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/JamesHeinrich/getID3/zipball/143af3325ee40e77c5d041d3f674c8bdd4762dc7", "url": "https://api.github.com/repos/JamesHeinrich/getID3/zipball/eb358a0d4943c0cc23e783f1a72141f46153c13a",
"reference": "143af3325ee40e77c5d041d3f674c8bdd4762dc7", "reference": "eb358a0d4943c0cc23e783f1a72141f46153c13a",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -738,7 +739,7 @@
"issues": "https://github.com/JamesHeinrich/getID3/issues", "issues": "https://github.com/JamesHeinrich/getID3/issues",
"source": "https://github.com/JamesHeinrich/getID3/tree/master" "source": "https://github.com/JamesHeinrich/getID3/tree/master"
}, },
"time": "2024-03-26T12:26:30+00:00" "time": "2024-09-20T19:45:51+00:00"
}, },
{ {
"name": "league/uri", "name": "league/uri",
@ -1099,20 +1100,20 @@
}, },
{ {
"name": "psr/http-factory", "name": "psr/http-factory",
"version": "1.0.2", "version": "1.1.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/php-fig/http-factory.git", "url": "https://github.com/php-fig/http-factory.git",
"reference": "e616d01114759c4c489f93b099585439f795fe35" "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
"reference": "e616d01114759c4c489f93b099585439f795fe35", "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=7.0.0", "php": ">=7.1",
"psr/http-message": "^1.0 || ^2.0" "psr/http-message": "^1.0 || ^2.0"
}, },
"type": "library", "type": "library",
@ -1136,7 +1137,7 @@
"homepage": "https://www.php-fig.org/" "homepage": "https://www.php-fig.org/"
} }
], ],
"description": "Common interfaces for PSR-7 HTTP message factories", "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories",
"keywords": [ "keywords": [
"factory", "factory",
"http", "http",
@ -1148,9 +1149,9 @@
"response" "response"
], ],
"support": { "support": {
"source": "https://github.com/php-fig/http-factory/tree/1.0.2" "source": "https://github.com/php-fig/http-factory"
}, },
"time": "2023-04-10T20:10:41+00:00" "time": "2024-04-15T12:06:14+00:00"
}, },
{ {
"name": "psr/http-message", "name": "psr/http-message",
@ -1318,21 +1319,22 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/scssphp/scssphp.git", "url": "https://github.com/scssphp/scssphp.git",
"reference": "5659341b5da400dafd5672171215f4534c06236b" "reference": "12d3cdf0fc2a73e9438ded5a5a82fb353b68d718"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/scssphp/scssphp/zipball/5659341b5da400dafd5672171215f4534c06236b", "url": "https://api.github.com/repos/scssphp/scssphp/zipball/12d3cdf0fc2a73e9438ded5a5a82fb353b68d718",
"reference": "5659341b5da400dafd5672171215f4534c06236b", "reference": "12d3cdf0fc2a73e9438ded5a5a82fb353b68d718",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-ctype": "*", "ext-ctype": "*",
"ext-json": "*", "ext-json": "*",
"league/uri": "^7.4@dev", "league/uri": "^7.4",
"league/uri-interfaces": "^7.3", "league/uri-interfaces": "^7.4",
"php": ">=8.1", "php": ">=8.1",
"symfony/filesystem": "^5.4 || ^6.0 || ^7.0" "symfony/filesystem": "^5.4 || ^6.0 || ^7.0",
"symfony/polyfill-mbstring": "^1.30"
}, },
"require-dev": { "require-dev": {
"bamarni/composer-bin-plugin": "^1.4", "bamarni/composer-bin-plugin": "^1.4",
@ -1347,8 +1349,7 @@
"zurb/foundation": "~6.7.0" "zurb/foundation": "~6.7.0"
}, },
"suggest": { "suggest": {
"ext-iconv": "Can be used as fallback when ext-mbstring is not available", "ext-mbstring": "For best performance, mbstring should be installed as it is faster than the polyfill"
"ext-mbstring": "For best performance, mbstring should be installed as it is faster than ext-iconv"
}, },
"default-branch": true, "default-branch": true,
"type": "library", "type": "library",
@ -1392,7 +1393,7 @@
"issues": "https://github.com/scssphp/scssphp/issues", "issues": "https://github.com/scssphp/scssphp/issues",
"source": "https://github.com/scssphp/scssphp/tree/main" "source": "https://github.com/scssphp/scssphp/tree/main"
}, },
"time": "2024-01-13T13:17:46+00:00" "time": "2024-10-24T15:03:30+00:00"
}, },
{ {
"name": "symfony/console", "name": "symfony/console",
@ -1400,12 +1401,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/console.git", "url": "https://github.com/symfony/console.git",
"reference": "39f75d9d73d0c11952fdcecf4877b4d0f62a8f6e" "reference": "108d436c2af470858bdaba3257baab3a74172017"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/39f75d9d73d0c11952fdcecf4877b4d0f62a8f6e", "url": "https://api.github.com/repos/symfony/console/zipball/108d436c2af470858bdaba3257baab3a74172017",
"reference": "39f75d9d73d0c11952fdcecf4877b4d0f62a8f6e", "reference": "108d436c2af470858bdaba3257baab3a74172017",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1491,20 +1492,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-02-20T16:33:57+00:00" "time": "2024-10-08T07:27:17+00:00"
}, },
{ {
"name": "symfony/deprecation-contracts", "name": "symfony/deprecation-contracts",
"version": "v3.4.0", "version": "v3.5.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git", "url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1",
"reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1513,7 +1514,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-main": "3.4-dev" "dev-main": "3.5-dev"
}, },
"thanks": { "thanks": {
"name": "symfony/contracts", "name": "symfony/contracts",
@ -1542,7 +1543,7 @@
"description": "A generic function and convention to trigger deprecation notices", "description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.4.0" "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0"
}, },
"funding": [ "funding": [
{ {
@ -1558,27 +1559,30 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-05-23T14:45:45+00:00" "time": "2024-04-18T09:32:20+00:00"
}, },
{ {
"name": "symfony/filesystem", "name": "symfony/filesystem",
"version": "v6.4.3", "version": "v7.2.0-BETA1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/filesystem.git", "url": "https://github.com/symfony/filesystem.git",
"reference": "7f3b1755eb49297a0827a7575d5d2b2fd11cc9fb" "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/7f3b1755eb49297a0827a7575d5d2b2fd11cc9fb", "url": "https://api.github.com/repos/symfony/filesystem/zipball/b8dce482de9d7c9fe2891155035a7248ab5c7fdb",
"reference": "7f3b1755eb49297a0827a7575d5d2b2fd11cc9fb", "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=8.1", "php": ">=8.2",
"symfony/polyfill-ctype": "~1.8", "symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-mbstring": "~1.8" "symfony/polyfill-mbstring": "~1.8"
}, },
"require-dev": {
"symfony/process": "^6.4|^7.0"
},
"type": "library", "type": "library",
"autoload": { "autoload": {
"psr-4": { "psr-4": {
@ -1605,7 +1609,7 @@
"description": "Provides basic utilities for the filesystem", "description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/filesystem/tree/v6.4.3" "source": "https://github.com/symfony/filesystem/tree/v7.2.0-BETA1"
}, },
"funding": [ "funding": [
{ {
@ -1621,24 +1625,24 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-01-23T14:51:35+00:00" "time": "2024-10-25T15:15:23+00:00"
}, },
{ {
"name": "symfony/polyfill-ctype", "name": "symfony/polyfill-ctype",
"version": "v1.29.0", "version": "v1.31.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git", "url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4" "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4", "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638",
"reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4", "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=7.1" "php": ">=7.2"
}, },
"provide": { "provide": {
"ext-ctype": "*" "ext-ctype": "*"
@ -1684,7 +1688,7 @@
"portable" "portable"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.29.0" "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0"
}, },
"funding": [ "funding": [
{ {
@ -1700,24 +1704,24 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-01-29T20:11:03+00:00" "time": "2024-09-09T11:45:10+00:00"
}, },
{ {
"name": "symfony/polyfill-intl-grapheme", "name": "symfony/polyfill-intl-grapheme",
"version": "v1.29.0", "version": "v1.31.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git",
"reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f" "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f", "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe",
"reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f", "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=7.1" "php": ">=7.2"
}, },
"suggest": { "suggest": {
"ext-intl": "For best performance" "ext-intl": "For best performance"
@ -1762,7 +1766,7 @@
"shim" "shim"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.29.0" "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0"
}, },
"funding": [ "funding": [
{ {
@ -1778,26 +1782,25 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-01-29T20:11:03+00:00" "time": "2024-09-09T11:45:10+00:00"
}, },
{ {
"name": "symfony/polyfill-intl-idn", "name": "symfony/polyfill-intl-idn",
"version": "v1.29.0", "version": "v1.31.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-intl-idn.git", "url": "https://github.com/symfony/polyfill-intl-idn.git",
"reference": "a287ed7475f85bf6f61890146edbc932c0fff919" "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/a287ed7475f85bf6f61890146edbc932c0fff919", "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/c36586dcf89a12315939e00ec9b4474adcb1d773",
"reference": "a287ed7475f85bf6f61890146edbc932c0fff919", "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=7.1", "php": ">=7.2",
"symfony/polyfill-intl-normalizer": "^1.10", "symfony/polyfill-intl-normalizer": "^1.10"
"symfony/polyfill-php72": "^1.10"
}, },
"suggest": { "suggest": {
"ext-intl": "For best performance" "ext-intl": "For best performance"
@ -1846,7 +1849,7 @@
"shim" "shim"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.29.0" "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.31.0"
}, },
"funding": [ "funding": [
{ {
@ -1862,24 +1865,24 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-01-29T20:11:03+00:00" "time": "2024-09-09T11:45:10+00:00"
}, },
{ {
"name": "symfony/polyfill-intl-normalizer", "name": "symfony/polyfill-intl-normalizer",
"version": "v1.29.0", "version": "v1.31.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git",
"reference": "bc45c394692b948b4d383a08d7753968bed9a83d" "reference": "3833d7255cc303546435cb650316bff708a1c75c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d", "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c",
"reference": "bc45c394692b948b4d383a08d7753968bed9a83d", "reference": "3833d7255cc303546435cb650316bff708a1c75c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=7.1" "php": ">=7.2"
}, },
"suggest": { "suggest": {
"ext-intl": "For best performance" "ext-intl": "For best performance"
@ -1927,7 +1930,7 @@
"shim" "shim"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.29.0" "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0"
}, },
"funding": [ "funding": [
{ {
@ -1943,24 +1946,24 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-01-29T20:11:03+00:00" "time": "2024-09-09T11:45:10+00:00"
}, },
{ {
"name": "symfony/polyfill-mbstring", "name": "symfony/polyfill-mbstring",
"version": "v1.29.0", "version": "v1.31.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git", "url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec" "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec", "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341",
"reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec", "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=7.1" "php": ">=7.2"
}, },
"provide": { "provide": {
"ext-mbstring": "*" "ext-mbstring": "*"
@ -2007,7 +2010,7 @@
"shim" "shim"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0" "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0"
}, },
"funding": [ "funding": [
{ {
@ -2023,97 +2026,24 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-01-29T20:11:03+00:00" "time": "2024-09-09T11:45:10+00:00"
},
{
"name": "symfony/polyfill-php72",
"version": "v1.29.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php72.git",
"reference": "861391a8da9a04cbad2d232ddd9e4893220d6e25"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/861391a8da9a04cbad2d232ddd9e4893220d6e25",
"reference": "861391a8da9a04cbad2d232ddd9e4893220d6e25",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"type": "library",
"extra": {
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Php72\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php72/tree/v1.29.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2024-01-29T20:11:03+00:00"
}, },
{ {
"name": "symfony/polyfill-php73", "name": "symfony/polyfill-php73",
"version": "v1.29.0", "version": "v1.31.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-php73.git", "url": "https://github.com/symfony/polyfill-php73.git",
"reference": "21bd091060673a1177ae842c0ef8fe30893114d2" "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/21bd091060673a1177ae842c0ef8fe30893114d2", "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/0f68c03565dcaaf25a890667542e8bd75fe7e5bb",
"reference": "21bd091060673a1177ae842c0ef8fe30893114d2", "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=7.1" "php": ">=7.2"
}, },
"type": "library", "type": "library",
"extra": { "extra": {
@ -2156,7 +2086,7 @@
"shim" "shim"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-php73/tree/v1.29.0" "source": "https://github.com/symfony/polyfill-php73/tree/v1.31.0"
}, },
"funding": [ "funding": [
{ {
@ -2172,24 +2102,24 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-01-29T20:11:03+00:00" "time": "2024-09-09T11:45:10+00:00"
}, },
{ {
"name": "symfony/polyfill-php80", "name": "symfony/polyfill-php80",
"version": "v1.29.0", "version": "v1.31.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-php80.git", "url": "https://github.com/symfony/polyfill-php80.git",
"reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b" "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8",
"reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=7.1" "php": ">=7.2"
}, },
"type": "library", "type": "library",
"extra": { "extra": {
@ -2236,7 +2166,7 @@
"shim" "shim"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.29.0" "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0"
}, },
"funding": [ "funding": [
{ {
@ -2252,25 +2182,26 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-01-29T20:11:03+00:00" "time": "2024-09-09T11:45:10+00:00"
}, },
{ {
"name": "symfony/service-contracts", "name": "symfony/service-contracts",
"version": "v3.4.1", "version": "v3.5.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/service-contracts.git", "url": "https://github.com/symfony/service-contracts.git",
"reference": "fe07cbc8d837f60caf7018068e350cc5163681a0" "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0", "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f",
"reference": "fe07cbc8d837f60caf7018068e350cc5163681a0", "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=8.1", "php": ">=8.1",
"psr/container": "^1.1|^2.0" "psr/container": "^1.1|^2.0",
"symfony/deprecation-contracts": "^2.5|^3"
}, },
"conflict": { "conflict": {
"ext-psr": "<1.1|>=2" "ext-psr": "<1.1|>=2"
@ -2278,7 +2209,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-main": "3.4-dev" "dev-main": "3.5-dev"
}, },
"thanks": { "thanks": {
"name": "symfony/contracts", "name": "symfony/contracts",
@ -2318,7 +2249,7 @@
"standards" "standards"
], ],
"support": { "support": {
"source": "https://github.com/symfony/service-contracts/tree/v3.4.1" "source": "https://github.com/symfony/service-contracts/tree/v3.5.0"
}, },
"funding": [ "funding": [
{ {
@ -2334,20 +2265,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-12-26T14:02:43+00:00" "time": "2024-04-18T09:32:20+00:00"
}, },
{ {
"name": "symfony/string", "name": "symfony/string",
"version": "v6.4.4", "version": "v6.4.13",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/string.git", "url": "https://github.com/symfony/string.git",
"reference": "4e465a95bdc32f49cf4c7f07f751b843bbd6dcd9" "reference": "38371c60c71c72b3d64d8d76f6b1bb81a2cc3627"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/4e465a95bdc32f49cf4c7f07f751b843bbd6dcd9", "url": "https://api.github.com/repos/symfony/string/zipball/38371c60c71c72b3d64d8d76f6b1bb81a2cc3627",
"reference": "4e465a95bdc32f49cf4c7f07f751b843bbd6dcd9", "reference": "38371c60c71c72b3d64d8d76f6b1bb81a2cc3627",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2404,7 +2335,7 @@
"utf8" "utf8"
], ],
"support": { "support": {
"source": "https://github.com/symfony/string/tree/v6.4.4" "source": "https://github.com/symfony/string/tree/v6.4.13"
}, },
"funding": [ "funding": [
{ {
@ -2420,7 +2351,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-02-01T13:16:41+00:00" "time": "2024-09-25T14:18:03+00:00"
}, },
{ {
"name": "vearutop/php-obscene-censor-rus", "name": "vearutop/php-obscene-censor-rus",
@ -2525,12 +2456,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/wapmorgan/Morphos.git", "url": "https://github.com/wapmorgan/Morphos.git",
"reference": "302b56636cf604ad07e20020076d8a4880554286" "reference": "d22876709756b538a52b30a50a3f37cd89efeb91"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/wapmorgan/Morphos/zipball/302b56636cf604ad07e20020076d8a4880554286", "url": "https://api.github.com/repos/wapmorgan/Morphos/zipball/d22876709756b538a52b30a50a3f37cd89efeb91",
"reference": "302b56636cf604ad07e20020076d8a4880554286", "reference": "d22876709756b538a52b30a50a3f37cd89efeb91",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2592,7 +2523,7 @@
"issues": "https://github.com/wapmorgan/Morphos/issues", "issues": "https://github.com/wapmorgan/Morphos/issues",
"source": "https://github.com/wapmorgan/Morphos/tree/master" "source": "https://github.com/wapmorgan/Morphos/tree/master"
}, },
"time": "2024-03-26T07:24:27+00:00" "time": "2024-09-26T12:41:09+00:00"
}, },
{ {
"name": "whichbrowser/parser", "name": "whichbrowser/parser",
@ -2600,12 +2531,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/WhichBrowser/Parser-PHP.git", "url": "https://github.com/WhichBrowser/Parser-PHP.git",
"reference": "1044880bc792dbce5948fbff22ae731c43c280d9" "reference": "581d614d686bfbec3529ad60562a5213ac5d8d72"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/WhichBrowser/Parser-PHP/zipball/1044880bc792dbce5948fbff22ae731c43c280d9", "url": "https://api.github.com/repos/WhichBrowser/Parser-PHP/zipball/581d614d686bfbec3529ad60562a5213ac5d8d72",
"reference": "1044880bc792dbce5948fbff22ae731c43c280d9", "reference": "581d614d686bfbec3529ad60562a5213ac5d8d72",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2629,8 +2560,7 @@
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"WhichBrowser\\": [ "WhichBrowser\\": [
"src/", "src/"
"tests/src/"
] ]
} }
}, },
@ -2655,28 +2585,28 @@
], ],
"support": { "support": {
"issues": "https://github.com/WhichBrowser/Parser-PHP/issues", "issues": "https://github.com/WhichBrowser/Parser-PHP/issues",
"source": "https://github.com/WhichBrowser/Parser-PHP/tree/v2.1.7" "source": "https://github.com/WhichBrowser/Parser-PHP/tree/v2.1.8"
}, },
"time": "2022-04-19T20:14:54+00:00" "time": "2024-04-17T12:47:41+00:00"
} }
], ],
"packages-dev": [], "packages-dev": [],
"aliases": [], "aliases": [],
"minimum-stability": "beta", "minimum-stability": "beta",
"stability-flags": { "stability-flags": {
"whichbrowser/parser": 20,
"james-heinrich/getid3": 20,
"rybakit/msgpack": 20,
"wapmorgan/binary-stream": 20,
"al/emoji-detector": 20, "al/emoji-detector": 20,
"ezyang/htmlpurifier": 20,
"scssphp/scssphp": 20,
"lfkeitel/phptotp": 20,
"vearutop/php-obscene-censor-rus": 20,
"erusev/parsedown": 20,
"bhaktaraz/php-rss-generator": 20, "bhaktaraz/php-rss-generator": 20,
"erusev/parsedown": 20,
"ezyang/htmlpurifier": 20,
"james-heinrich/getid3": 20,
"lfkeitel/phptotp": 20,
"rybakit/msgpack": 20,
"scssphp/scssphp": 20,
"symfony/console": 20, "symfony/console": 20,
"wapmorgan/morphos": 20 "vearutop/php-obscene-censor-rus": 20,
"wapmorgan/binary-stream": 20,
"wapmorgan/morphos": 20,
"whichbrowser/parser": 20
}, },
"prefer-stable": false, "prefer-stable": false,
"prefer-lowest": false, "prefer-lowest": false,
@ -2684,8 +2614,9 @@
"php": "~7.3||~8.1", "php": "~7.3||~8.1",
"ext-openssl": "*", "ext-openssl": "*",
"ext-simplexml": "*", "ext-simplexml": "*",
"ext-sodium": "*" "ext-sodium": "*",
"ext-iconv": "*"
}, },
"platform-dev": [], "platform-dev": {},
"plugin-api-version": "2.3.0" "plugin-api-version": "2.6.0"
} }

View file

@ -1,51 +1,55 @@
# Docker # Docker
Note: `buildx` is required for building multi-arch images. See [Docker Buildx](https://docs.docker.com/buildx/working-with-buildx/) for more information. Note: If you want to build images for multiple architectures, you must use `buildx`. See [Docker Buildx](https://docs.docker.com/buildx/working-with-buildx/) for more information.
If unsure, skip to single-arch image build instructions. If unsure, skip to single-arch image build instructions.
## Build ## Build
Note: commands below should be run from the root of the repository. Note: **commands below must be run from the this directory** (`/install/automated/docker/`).
### Multi-arch (arm64, amd64) ### Multi-arch (arm64, amd64)
Base images: Base images:
``` ```
docker buildx build --platform linux/amd64,linux/arm64 -t ghcr.io/openvk/openvk/php:8.2-cli . --load -f install/automated/docker/base-php-cli.Dockerfile docker buildx build --platform linux/amd64,linux/arm64 -t ghcr.io/openvk/openvk/php:8.2-cli ../../.. --load -f base-php-cli.Dockerfile
docker buildx build --platform linux/amd64,linux/arm64 -t ghcr.io/openvk/openvk/php:8.2-apache . --load -f install/automated/docker/base-php-apache.Dockerfile docker buildx build --platform linux/amd64,linux/arm64 -t ghcr.io/openvk/openvk/php:8.2-apache ../../.. --load -f base-php-apache.Dockerfile
``` ```
DB images: DB images:
``` ```
docker buildx build --platform linux/amd64,linux/arm64 -t ghcr.io/openvk/openvk/mariadb:10.9-primary . --load -f install/automated/docker/mariadb-primary.Dockerfile docker buildx build --platform linux/amd64,linux/arm64 -t ghcr.io/openvk/openvk/mariadb:10.9-primary ../../.. --load -f mariadb-primary.Dockerfile
docker buildx build --platform linux/amd64,linux/arm64 -t ghcr.io/openvk/openvk/mariadb:10.9-eventdb . --load -f install/automated/docker/mariadb-eventdb.Dockerfile docker buildx build --platform linux/amd64,linux/arm64 -t ghcr.io/openvk/openvk/mariadb:10.9-eventdb ../../.. --load -f mariadb-eventdb.Dockerfile
``` ```
OpenVK main image: OpenVK main image:
``` ```
docker buildx build --platform linux/amd64,linux/arm64 -t ghcr.io/openvk/openvk/openvk:latest . --load -f install/automated/docker/openvk.Dockerfile docker buildx build --platform linux/amd64,linux/arm64 -t ghcr.io/openvk/openvk/openvk:latest ../../.. --load -f openvk.Dockerfile
``` ```
### Single-arch ### Single-arch
Base images: Base images:
``` ```
docker build -t ghcr.io/openvk/openvk/php:8.2-cli . -f install/automated/docker/base-php-cli.Dockerfile docker build -t ghcr.io/openvk/openvk/php:8.2-cli ../../.. -f base-php-cli.Dockerfile
docker build -t ghcr.io/openvk/openvk/php:8.2-apache . -f install/automated/docker/base-php-apache.Dockerfile docker build -t ghcr.io/openvk/openvk/php:8.2-apache ../../.. -f base-php-apache.Dockerfile
``` ```
DB images: DB images:
``` ```
docker build -t ghcr.io/openvk/openvk/mariadb:10.9-primary . -f install/automated/docker/mariadb-primary.Dockerfile docker build -t ghcr.io/openvk/openvk/mariadb:10.9-primary ../../.. -f mariadb-primary.Dockerfile
docker build -t ghcr.io/openvk/openvk/mariadb:10.9-eventdb . -f install/automated/docker/mariadb-eventdb.Dockerfile docker build -t ghcr.io/openvk/openvk/mariadb:10.9-eventdb ../../.. --f mariadb-eventdb.Dockerfile
``` ```
OpenVK main image: OpenVK main image:
``` ```
docker build -t ghcr.io/openvk/openvk/openvk:latest . -f install/automated/docker/openvk.Dockerfile docker build -t ghcr.io/openvk/openvk/openvk:latest ../../.. -f openvk.Dockerfile
``` ```
## Run ## Run
If you have Docker Desktop installed, then you probably have `docker-compose` installed as well. If not, refer to [Docker Compose](https://docs.docker.com/compose/install/) for installation instructions. If you have Docker Desktop installed, then you should have `docker compose` installed automatically. If not, refer to [Docker Compose](https://docs.docker.com/compose/install/) for installation instructions.
Before start, copy `openvk-example.yml` from the root of the repository to `openvk.yml` in this directory and edit it to your liking. Example configurations are located in this directory for convenience. Before start, copy `openvk.example.yml` to `openvk.yml`, then `chandler.example.yml` to `chandler.yml` and edit them to your liking.
Then, obtain `chandler-example.yml` from [chandler repository](https://github.com/openvk/chandler/blob/master/chandler-example.yml) and place it in this directory as well. Start is simple as `docker compose up -d`. You can also use `docker compose up` to see logs.
Start is simple as `docker-compose up -d`. You can also use `docker-compose up` to see logs.
- OpenVK will be available at `http://localhost:8080/`. - OpenVK will be available at `http://localhost:8080/`.
- PHPMyAdmin will be available at `http://localhost:8081/`. - PHPMyAdmin will be available at `http://localhost:8081/`.
- Adminer will be available at `http://localhost:8082/`. - Adminer will be available at `http://localhost:8082/`.
### Running in development environment
By using additional `docker-compose.dev.yml` file you can develop OpenVK in Docker with automatic updates as you edit and save your code. Simply run:
```
docker compose -f docker-compose.yml -f docker-compose.dev.yml up --watch
```

View file

@ -0,0 +1,20 @@
services:
openvk:
build:
context: ../../..
dockerfile: install/automated/docker/openvk.Dockerfile
develop:
watch:
- path: ../../..
action: sync
target: /opt/chandler/extensions/available/openvk
ignore:
- vendor/
- path: ../../../composer.json
action: rebuild
- path: ../../../composer.lock
action: rebuild
- path: ../../../Web/static/js/package-lock.json
action: rebuild
- path: ../../../Web/static/js/package.json
action: rebuild

View file

@ -1,4 +1,4 @@
version: '3.7' name: openvk
services: services:
openvk: openvk:

View file

@ -57,4 +57,6 @@ VOLUME [ "/opt/chandler/extensions/available/openvk/tmp/api-storage/audios" ]
VOLUME [ "/opt/chandler/extensions/available/openvk/tmp/api-storage/photos" ] VOLUME [ "/opt/chandler/extensions/available/openvk/tmp/api-storage/photos" ]
VOLUME [ "/opt/chandler/extensions/available/openvk/tmp/api-storage/videos" ] VOLUME [ "/opt/chandler/extensions/available/openvk/tmp/api-storage/videos" ]
USER www-data USER www-data
WORKDIR /opt/chandler/extensions/available/openvk

View file

@ -0,0 +1,2 @@
ALTER TABLE `posts`
ADD COLUMN `source` TEXT NULL DEFAULT NULL AFTER `api_source_name`;

View file

@ -111,7 +111,7 @@
"relationship_4" = "Married"; "relationship_4" = "Married";
"relationship_5" = "In a civil marriage"; "relationship_5" = "In a civil marriage";
"relationship_6" = "In love"; "relationship_6" = "In love";
"relationship_7" = "Everything is complicated"; "relationship_7" = "It's complicated";
"relationship_8" = "Actively searching"; "relationship_8" = "Actively searching";
/* xd */ /* xd */
@ -122,7 +122,7 @@
"relationship_6_prefix" = "with"; "relationship_6_prefix" = "with";
"relationship_7_prefix" = "with"; "relationship_7_prefix" = "with";
"politViews" = "Polit. Views"; "politViews" = "Political views";
"politViews_0" = "Not Selected"; "politViews_0" = "Not Selected";
"politViews_1" = "Indifferent"; "politViews_1" = "Indifferent";
@ -156,7 +156,7 @@
"updated_at" = "Updated at $1"; "updated_at" = "Updated at $1";
"user_banned" = "Unfortunately, we had to block the <b>$1</b> user page."; "user_banned" = "Unfortunately, we had to block <b>$1's</b> user page.";
"user_banned_comment" = "Moderator's comment:"; "user_banned_comment" = "Moderator's comment:";
"verified_page" = "Verified page"; "verified_page" = "Verified page";
"user_is_blocked" = "User is blocked"; "user_is_blocked" = "User is blocked";
@ -201,11 +201,11 @@
"pin" = "Pin"; "pin" = "Pin";
"unpin" = "Unpin"; "unpin" = "Unpin";
"pinned" = "pinned"; "pinned" = "pinned";
"comments_tip" = "Be first, who leaves a comment at this post!"; "comments_tip" = "Be the first to leave a comment on this post!";
"your_comment" = "Your comment"; "your_comment" = "Your comment";
"auditory" = "Auditory"; "auditory" = "Auditory";
"in_wall" = "to user's wall"; "in_wall" = "to my wall";
"in_group" = "to group"; "in_group" = "to a group";
"shown" = "Shown"; "shown" = "Shown";
"x_out_of" = "$1 of"; "x_out_of" = "$1 of";
"wall_zero" = "no posts"; "wall_zero" = "no posts";
@ -223,6 +223,12 @@
"attachment" = "Attachment"; "attachment" = "Attachment";
"post_as_group" = "Post as group"; "post_as_group" = "Post as group";
"comment_as_group" = "Comment as group"; "comment_as_group" = "Comment as group";
"add_source" = "Add source";
"set_source" = "Apply source";
"source" = "Source";
"set_source_tip" = "If you are using content from other authors, it is important to provide a source to the original.<br>You can do it below.";
"add_signature" = "Add signature"; "add_signature" = "Add signature";
/* ^ can be translated as "author's signature". ^ */ /* ^ can be translated as "author's signature". ^ */
"contains_nsfw" = "Contains NSFW content"; "contains_nsfw" = "Contains NSFW content";
@ -236,7 +242,7 @@
"no_posts_abstract" = "Nobody wrote anything here... So far."; "no_posts_abstract" = "Nobody wrote anything here... So far.";
"attach_no_longer_available" = "This attachment is no longer available."; "attach_no_longer_available" = "This attachment is no longer available.";
"open_post" = "Open post"; "open_post" = "Open post";
"version_incompatibility" = "This attachment could not be displayed. Probably the database is incompatible with the current version of OpenVK."; "version_incompatibility" = "This attachment could not be displayed. Probably because the database is incompatible with the current version of OpenVK.";
"graffiti" = "Graffiti"; "graffiti" = "Graffiti";
@ -317,8 +323,8 @@
"create_group" = "Create group"; "create_group" = "Create group";
"group_managers" = "Managers"; "group_managers" = "Managers";
"group_type" = "Group type"; "group_type" = "Group type";
"group_type_open" = "This is an open group, anyone can enter it."; "group_type_open" = "This is an open group. Anyone can enter it.";
"group_type_closed" = "This is an closed group. To enter, you must submit an request."; "group_type_closed" = "This is a closed group. To enter, you must submit a request.";
"creator" = "Creator"; "creator" = "Creator";
"administrators" = "Administrators"; "administrators" = "Administrators";
"add_to_left_menu" = "Add to left menu"; "add_to_left_menu" = "Add to left menu";
@ -357,12 +363,12 @@
"suggested_by_everyone_many" = "$1 suggested posts"; "suggested_by_everyone_many" = "$1 suggested posts";
"suggested_by_everyone_other" = "$1 suggested posts"; "suggested_by_everyone_other" = "$1 suggested posts";
"group_hide_from_global_feed" = "Don't display posts in the global feed"; "group_hide_from_global_feed" = "Don't display posts in global feed";
"suggested_posts_by_you" = "Suggested posts by you"; "suggested_posts_by_you" = "Your suggested posts";
"suggested_posts_by_everyone" = "Suggested posts"; "suggested_posts_by_everyone" = "Suggested posts";
"suggested" = "Suggested"; "suggested" = "Suggested";
"suggested_posts_everyone" = "Suggested by users posts"; "suggested_posts_everyone" = "Posts suggested by users";
"no_suggested_posts_by_you" = "You haven't suggested posts to this group yet."; "no_suggested_posts_by_you" = "You haven't suggested any post to this group yet.";
"no_suggested_posts_by_people" = "No posts have been suggested to this group yet."; "no_suggested_posts_by_people" = "No posts have been suggested to this group yet.";
"publish_suggested" = "Accept"; "publish_suggested" = "Accept";
@ -377,23 +383,24 @@
"suggested_posts_in_group_many" = "This group has $1 suggested posts"; "suggested_posts_in_group_many" = "This group has $1 suggested posts";
"suggested_posts_in_group_other" = "This group has $1 suggested posts"; "suggested_posts_in_group_other" = "This group has $1 suggested posts";
"suggested_posts_in_group_by_you_zero" = "You haven't suggested any posts to this group"; "suggested_posts_in_group_by_you_zero" = "You haven't suggested any post to this group";
"suggested_posts_in_group_by_you_one" = "You suggested one post to this group"; "suggested_posts_in_group_by_you_one" = "You suggested one post to this group";
"suggested_posts_in_group_by_you_few" = "You suggested $1 posts to this group"; "suggested_posts_in_group_by_you_few" = "You suggested $1 posts to this group";
"suggested_posts_in_group_by_you_many" = "You suggested $1 posts to this group"; "suggested_posts_in_group_by_you_many" = "You suggested $1 posts to this group";
"suggested_posts_in_group_by_you_other" = "You suggested $1 posts to this group"; "suggested_posts_in_group_by_you_other" = "You suggested $1 posts to this group";
"suggestion_succefully_published" = "Post successfully published"; "suggestion_successfully_published" = "Post successfully published";
"suggestion_succefully_declined" = "Post successfully declined"; "suggestion_successfully_declined" = "Post successfully declined";
"suggestion_press_to_go" = "Click to show it"; "suggestion_press_to_go" = "Go to post";
"error_declining_invalid_post" = "Error when declining post: post does not exists"; "error_declining_invalid_post" = "The suggested post you attempted to decline is invalid";
"error_declining_not_suggested_post" = "Error when declining post: post is not suggested"; "error_declining_not_suggested_post" = "The post you attempted to decline is not suggested";
"error_declining_declined_post" = "Error when declining post: post is already declined"; "error_declining_declined_post" = "This suggested post has already been declined";
"error_accepting_invalid_post" = "The suggested post you attempted to accept is invalid";
"error_accepting_not_suggested_post" = "The post you attempted to accept is not suggested";
"error_accepting_declined_post" = "This suggested post has already been declined";
"error_accepting_invalid_post" = "Error when accepting post: post does not exists";
"error_accepting_not_suggested_post" = "Error when accepting post: post is not suggested";
"error_accepting_declined_post" = "Error when accepting post: cant accept declined post";
"statistics" = "Statistics"; "statistics" = "Statistics";
"group_administrators_list" = "Admins list"; "group_administrators_list" = "Admins list";
"group_display_only_creator" = "Display only group creator"; "group_display_only_creator" = "Display only group creator";
@ -483,6 +490,7 @@
"deleting_avatar" = "Deleting photo"; "deleting_avatar" = "Deleting photo";
"deleting_avatar_sure" = "Do you sure you want to delete avatar?"; "deleting_avatar_sure" = "Do you sure you want to delete avatar?";
"deleted_avatar_notification" = "Picture deleted successfully";
"save_changes" = "Save changes"; "save_changes" = "Save changes";
"upd_m" = "updated his profile picture"; "upd_m" = "updated his profile picture";
@ -493,7 +501,7 @@
"add_photos" = "Add photos"; "add_photos" = "Add photos";
"upload_picts" = "Upload photos"; "upload_picts" = "Upload photos";
"end_uploading" = "Finish uploading"; "end_uploading" = "Finish uploading";
"photos_successfully_uploaded" = "Photos successfully uploaded"; "photos_successfully_uploaded" = "Photos uploaded successfully";
"click_to_go_to_album" = "Click here to go to album."; "click_to_go_to_album" = "Click here to go to album.";
"error_uploading_photo" = "Error when uploading photo"; "error_uploading_photo" = "Error when uploading photo";
"too_many_pictures" = "No more than 10 pictures"; "too_many_pictures" = "No more than 10 pictures";
@ -553,10 +561,10 @@
"error_attaching_note" = "Error when attaching note"; "error_attaching_note" = "Error when attaching note";
"select_or_create_new" = "Select existing note or <a href='/notes/create'>create new one</a>"; "select_or_create_new" = "Select an existing note or <a href='/notes/create'>create a new one</a>";
"notes_closed" = "You can't attach note to post, because only you can see them.<br> You can change it in <a href=\"/settings?act=privacy\">settings</a>."; "notes_closed" = "You can't attach a note to the post because only you can see them.<br> You can change this in <a href=\"/settings?act=privacy\">settings</a>.";
"do_not_attach_note" = "Do not attach note"; "do_not_attach_note" = "Do not attach a note";
"something" = "Something"; "something" = "Something";
"supports_xhtml" = "from (X)HTML supported."; "supports_xhtml" = "from (X)HTML supported.";
@ -579,15 +587,15 @@
"my_feed" = "My Feed"; "my_feed" = "My Feed";
"my_feedback" = "My Feedback"; "my_feedback" = "My Feedback";
"my_settings" = "My Settings"; "my_settings" = "My Settings";
"bug_tracker" = "Bug-tracker"; "bug_tracker" = "Bug Tracker";
"menu_settings" = "Settings"; "menu_settings" = "Settings";
"menu_login" = "Login"; "menu_login" = "Login";
"menu_registration" = "Registration"; "menu_registration" = "Register";
"menu_help" = "Help"; "menu_help" = "Help";
"menu_logout" = "Logout"; "menu_logout" = "Log out";
"menu_support" = "Support"; "menu_support" = "Support";
"header_home" = "home"; "header_home" = "home";
@ -834,6 +842,7 @@
/* Audios */ /* Audios */
"my" = "My";
"audios" = "Audios"; "audios" = "Audios";
"audio" = "Audio"; "audio" = "Audio";
"playlist" = "Playlist"; "playlist" = "Playlist";
@ -849,16 +858,16 @@
"limits" = "Limits"; "limits" = "Limits";
"select_audio" = "Select audio from your computer"; "select_audio" = "Select audio from your computer";
"audio_requirements" = "Audio must be between $1 seconds to $2 minutes, weights to $3 MB and contain audio stream."; "audio_requirements" = "Audio must be between $1 seconds and $2 minutes, with a file size up to $3 MB, and contain an audio stream.";
"audio_requirements_2" = "Audio must not infringe copyright and related rights"; "audio_requirements_2" = "Audio must not infringe copyright and related rights.";
"you_can_also_add_audio_using" = "You can also add audio from among the files you have already downloaded using"; "you_can_also_add_audio_using" = "You can also add audio from files you have already downloaded using";
"search_audio_inst" = "audios search"; "search_audio_inst" = "audios search";
"audio_embed_not_found" = "Audio not found"; "audio_embed_not_found" = "Audio not found";
"audio_embed_deleted" = "Audio was deleted"; "audio_embed_deleted" = "Audio has been deleted";
"audio_embed_withdrawn" = "The audio was withdrawn at the request of the copyright holder"; "audio_embed_withdrawn" = "The audio has been withdrawn at the request of the copyright holder";
"audio_embed_forbidden" = "The user's privacy settings do not allow this audio to be embedded"; "audio_embed_forbidden" = "The user's privacy settings do not allow this audio to be embedded";
"audio_embed_processing" = "Audio is still being processed, or has not been processed correctly."; "audio_embed_processing" = "Audio is still being processed or has not been processed correctly.";
"audios_count_zero" = "No audios"; "audios_count_zero" = "No audios";
"audios_count_one" = "One audio"; "audios_count_one" = "One audio";
@ -871,7 +880,7 @@
"my_music" = "My music"; "my_music" = "My music";
"music_user" = "User's music"; "music_user" = "User's music";
"music_club" = "Club's music"; "music_club" = "Group's music";
"audio_new" = "New"; "audio_new" = "New";
"audio_popular" = "Popular"; "audio_popular" = "Popular";
"audio_search" = "Search"; "audio_search" = "Search";
@ -914,19 +923,19 @@
"delete_playlist" = "Delete playlist"; "delete_playlist" = "Delete playlist";
"playlist_cover" = "Playlist cover"; "playlist_cover" = "Playlist cover";
"playlists_user" = "Users playlists"; "playlists_user" = "User's playlists";
"playlists_club" = "Groups playlists"; "playlists_club" = "Group's playlists";
"change_cover" = "Change cover"; "change_cover" = "Change cover";
"playlist_cover" = "Playlist's cover"; "playlist_cover" = "Playlist's cover";
"minutes_count_zero" = "lasts no minutes"; "minutes_count_zero" = "Lasts no minutes";
"minutes_count_one" = "lasts one minute"; "minutes_count_one" = "Lasts one minute";
"minutes_count_few" = "lasts $1 minutes"; "minutes_count_few" = "Lasts $1 minutes";
"minutes_count_many" = "lasts $1 minutes"; "minutes_count_many" = "Lasts $1 minutes";
"minutes_count_other" = "lasts $1 minutes"; "minutes_count_other" = "Lasts $1 minutes";
"listens_count_zero" = "no listens"; "listens_count_zero" = "No listens";
"listens_count_one" = "one listen"; "listens_count_one" = "One listen";
"listens_count_few" = "$1 listens"; "listens_count_few" = "$1 listens";
"listens_count_many" = "$1 listens"; "listens_count_many" = "$1 listens";
"listens_count_other" = "$1 listens"; "listens_count_other" = "$1 listens";
@ -949,7 +958,7 @@
"audio_successfully_uploaded" = "Audio has been successfully uploaded and is currently being processed."; "audio_successfully_uploaded" = "Audio has been successfully uploaded and is currently being processed.";
"broadcast_audio" = "Broadcast audio to status"; "broadcast_audio" = "Broadcast audio to status";
"sure_delete_playlist" = "Do you sure want to delete this playlist?"; "sure_delete_playlist" = "Are you sure you want to delete this playlist?";
"edit_audio" = "Edit audio"; "edit_audio" = "Edit audio";
"audios_group" = "Audios from group"; "audios_group" = "Audios from group";
"playlists_group" = "Playlists from group"; "playlists_group" = "Playlists from group";
@ -1057,7 +1066,7 @@
"coins_count" = "Number of votes"; "coins_count" = "Number of votes";
"message" = "Message"; "message" = "Message";
"failed_to_tranfer_points" = "Failed to transfer votes"; "failed_to_transfer_points" = "Failed to transfer votes";
"points_transfer_successful" = "You have successfully transferred <b>$1</b> to <b><a href=\"$2\">$3</a></b>."; "points_transfer_successful" = "You have successfully transferred <b>$1</b> to <b><a href=\"$2\">$3</a></b>.";
"not_all_information_has_been_entered" = "Not all information has been entered."; "not_all_information_has_been_entered" = "Not all information has been entered.";
@ -1076,8 +1085,8 @@
"apply_voucher" = "Apply voucher"; "apply_voucher" = "Apply voucher";
"failed_to_increase_rating" = "Failed to increase rating"; "failed_to_increase_rating" = "Failed to increase rating";
"rating_increase_successful" = "You have successfully increased rating of <b><a href=\"$1\">$2</a></b> by <b>$3%</b>."; "rating_increase_successful" = "You have successfully increased the rating of <b><a href=\"$1\">$2</a></b> by <b>$3%</b>.";
"negative_rating_value" = "We cannot steal rating from another person, sorry."; "negative_rating_value" = "You can't steal ratings from another person.";
"increased_your_rating_by" = "increased your rating by"; "increased_your_rating_by" = "increased your rating by";
@ -1138,43 +1147,43 @@
"app_withdrawal_empty" = "Sorry, withdrawal of emptiness is not possible."; "app_withdrawal_empty" = "Sorry, withdrawal of emptiness is not possible.";
"app_withdrawal_created" = "A request to withdraw $1 votes has been created. Awaiting crediting."; "app_withdrawal_created" = "A request to withdraw $1 votes has been created. Awaiting crediting.";
"appjs_payment" = "Purchase payment"; "appjs_payment" = "Purchase Payment";
"appjs_payment_intro" = "You are about to pay for an order in the application"; "appjs_payment_intro" = "You are about to pay for an order in the application";
"appjs_order_items" = "Order items"; "appjs_order_items" = "Order items";
"appjs_payment_total" = "Total amount payable"; "appjs_payment_total" = "Total amount payable";
"appjs_payment_confirm" = "Pay"; "appjs_payment_confirm" = "Pay";
"appjs_err_funds" = "Failed to pay: insufficient funds."; "appjs_err_funds" = "Failed to pay: insufficient funds.";
"appjs_wall_post" = "Publish a post"; "appjs_wall_post" = "Publish a Post";
"appjs_wall_post_desc" = "wants to publish a post on your wall"; "appjs_wall_post_desc" = "wants to publish a post on your wall";
"appjs_act_friends" = "your Friends"; "appjs_act_friends" = "Your Friends";
"appjs_act_friends_desc" = "add users as friends and read your friends list"; "appjs_act_friends_desc" = "add users as friends and read your friends list";
"appjs_act_wall" = "your Wall"; "appjs_act_wall" = "Your Wall";
"appjs_act_wall_desc" = "see your news, your wall and create posts on it"; "appjs_act_wall_desc" = "see your news, your wall and create posts on it";
"appjs_act_messages" = "your Messages"; "appjs_act_messages" = "Your Messages";
"appjs_act_messages_desc" = "read and write messages on your behalf"; "appjs_act_messages_desc" = "read and write messages on your behalf";
"appjs_act_groups" = "your Groups"; "appjs_act_groups" = "Your Groups";
"appjs_act_groups_desc" = "see a list of your groups and subscribe you to other"; "appjs_act_groups_desc" = "see a list of your groups and subscribe you to others";
"appjs_act_likes" = "Likes feature"; "appjs_act_likes" = "Likes Feature";
"appjs_act_likes_desc" = "give and take away likes to posts"; "appjs_act_likes_desc" = "give and take away likes to posts";
"appjs_act_request" = "Access request"; "appjs_act_request" = "Access Request";
"appjs_act_requests" = "requests access to"; "appjs_act_requests" = "requests access to";
"appjs_act_can" = "The app will be able to"; "appjs_act_can" = "The app will be able to";
"appjs_act_allow" = "Allow"; "appjs_act_allow" = "Allow";
"appjs_act_disallow" = "Disallow"; "appjs_act_disallow" = "Disallow";
"app_uninstalled" = "Application is disabled"; "app_uninstalled" = "Application Disabled";
"app_uninstalled_desc" = "It will no longer be able to perform actions on your behalf."; "app_uninstalled_desc" = "It will no longer be able to perform actions on your behalf.";
"app_err_not_found" = "Application not found"; "app_err_not_found" = "Application Not Found";
"app_err_not_found_desc" = "Incorrect identifier or it has been disabled."; "app_err_not_found_desc" = "Incorrect identifier or it has been disabled.";
"app_err_forbidden_desc" = "This application is not yours."; "app_err_forbidden_desc" = "This application does not belong to you.";
"app_err_url" = "Incorrect address"; "app_err_url" = "Incorrect Address";
"app_err_url_desc" = "The address of the application did not pass the check, make sure it is correct."; "app_err_url_desc" = "The address of the application did not pass the check; make sure it is correct.";
"app_err_ava" = "Unable to upload an avatar"; "app_err_ava" = "Unable to Upload an Avatar";
"app_err_ava_desc" = "Avatar too big or wrong: general error #$res."; "app_err_ava_desc" = "Avatar is too big or incorrect: general error #$res.";
"app_err_note" = "Failed to attach a news note"; "app_err_note" = "Failed to Attach a News Note";
"app_err_note_desc" = "Make sure the link is correct and the note belongs to you."; "app_err_note_desc" = "Make sure the link is correct and the note belongs to you.";
"learn_more" = "Learn more"; "learn_more" = "Learn more";
@ -1182,7 +1191,7 @@
/* Support */ /* Support */
"support_opened" = "Opened"; "support_opened" = "Opened";
"support_answered" = "With a response"; "support_answered" = "Has a response";
"support_closed" = "Closed"; "support_closed" = "Closed";
"support_ticket" = "Ticket"; "support_ticket" = "Ticket";
"support_tickets" = "Tickets"; "support_tickets" = "Tickets";
@ -1190,28 +1199,28 @@
"support_status_1" = "There's a response"; "support_status_1" = "There's a response";
"support_status_2" = "Closed"; "support_status_2" = "Closed";
"support_greeting_hi" = "Greetings, $1!"; "support_greeting_hi" = "Greetings, $1!";
"support_greeting_regards" = "Best regards,<br/>$1 support team."; "support_greeting_regards" = "Best regards,<br/>$1 Support Team.";
"support_faq" = "Frequently Asked Questions"; "support_faq" = "Frequently Asked Questions";
"support_list" = "List of tickets"; "support_list" = "List of Tickets";
"support_new" = "New ticket"; "support_new" = "New Ticket";
"support_new_title" = "Enter the topic of your ticket"; "support_new_title" = "Enter the topic of your ticket";
"support_new_content" = "Describe the issue or suggestion"; "support_new_content" = "Describe the issue or suggestion";
"reports" = "Reports"; "reports" = "Reports";
"support_rate_good_answer" = "This is good answer"; "support_rate_good_answer" = "This is a good answer";
"support_rate_bad_answer" = "This is bad answer"; "support_rate_bad_answer" = "This is a bad answer";
"support_good_answer_user" = "You left a positive feedback."; "support_good_answer_user" = "You left positive feedback.";
"support_bad_answer_user" = "You left a negative feedback."; "support_bad_answer_user" = "You left negative feedback.";
"support_good_answer_agent" = "User left a positive feedback."; "support_good_answer_agent" = "User left positive feedback.";
"support_bad_answer_agent" = "User left a negative feedback."; "support_bad_answer_agent" = "User left negative feedback.";
"support_rated_good" = "You left a positive feedback about the answer."; "support_rated_good" = "You left positive feedback about the answer.";
"support_rated_bad" = "You left a negative feedback about the answer."; "support_rated_bad" = "You left negative feedback about the answer.";
"wrong_parameters" = "Invalid request parameters."; "wrong_parameters" = "Invalid request parameters.";
"fast_answers" = "Fast answers"; "fast_answers" = "Quick Answers";
"ignore_report" = "Ignore report"; "ignore_report" = "Ignore report";
"report_number" = "Report #"; "report_number" = "Report #";
@ -1306,7 +1315,7 @@
"poll_editor_tips" = "Pressing backspace in empty option will remove it. Use Tab/Enter (in last option) to create new options faster."; "poll_editor_tips" = "Pressing backspace in empty option will remove it. Use Tab/Enter (in last option) to create new options faster.";
"poll_embed" = "Embed code"; "poll_embed" = "Embed code";
"poll_voter_count_zero" = "Be <b>the first one</b> to vote!"; "poll_voter_count_zero" = "Be <b>the first</b> to vote!";
"poll_voter_count_one" = "<b>Only one</b> user voted."; "poll_voter_count_one" = "<b>Only one</b> user voted.";
"poll_voter_count_few" = "<b>$1</b> users voted."; "poll_voter_count_few" = "<b>$1</b> users voted.";
"poll_voter_count_many" = "<b>$1</b> users voted."; "poll_voter_count_many" = "<b>$1</b> users voted.";
@ -1333,7 +1342,7 @@
"messages_other" = "$1 messages"; "messages_other" = "$1 messages";
"topic_messages_count_zero" = "Topic has no messages"; "topic_messages_count_zero" = "Topic has no messages";
"topic_messages_count_one" = "There are one message in the topic"; "topic_messages_count_one" = "There is one message in the topic";
"topic_messages_count_other" = "There are $1 messages in the topic"; "topic_messages_count_other" = "There are $1 messages in the topic";
"replied" = "replied"; "replied" = "replied";
@ -1399,7 +1408,7 @@
"photo_saved" = "Photo saved"; "photo_saved" = "Photo saved";
"photo_saved_comment" = "New profile picture will appear on your page"; "photo_saved_comment" = "New profile picture will appear on your page";
"shared_succ" = "The post will appear on your wall. Click on the notification to go to your wall."; "shared_succ" = "The post will appear on your wall. Click on this notification to go there.";
"invalid_email_address" = "Invalid Email address"; "invalid_email_address" = "Invalid Email address";
"invalid_email_address_comment" = "The Email you entered is not correct."; "invalid_email_address_comment" = "The Email you entered is not correct.";
@ -1553,6 +1562,10 @@
"ffmpeg_not_installed" = "Failed to proccess the file. It looks like ffmpeg is not installed on this server."; "ffmpeg_not_installed" = "Failed to proccess the file. It looks like ffmpeg is not installed on this server.";
"too_many_or_to_lack" = "Too few or too many sources."; "too_many_or_to_lack" = "Too few or too many sources.";
"error_adding_source_regex" = "Error adding source: incorrect link.";
"error_adding_source_long" = "Error adding source: link is too long.";
"error_adding_source_sus" = "Error adding source: suspicious link.";
/* Admin actions */ /* Admin actions */
"login_as" = "Login as $1"; "login_as" = "Login as $1";
@ -1993,6 +2006,7 @@
/* Search */ /* Search */
"s_params" = "Search params";
"s_people" = "Users"; "s_people" = "Users";
"s_groups" = "Clubs"; "s_groups" = "Clubs";
"s_apps" = "Applications"; "s_apps" = "Applications";

View file

@ -207,6 +207,12 @@
"attachment" = "Вложение"; "attachment" = "Вложение";
"post_as_group" = "От имени сообщества"; "post_as_group" = "От имени сообщества";
"comment_as_group" = "От имени сообщества"; "comment_as_group" = "От имени сообщества";
"add_source" = "Добавление источника";
"set_source" = "Указать источник";
"source" = "Источник";
"set_source_tip" = "Если вы используете материалы других авторов, важно указывать ссылку на оригинал.<br>Сделать это вы можете ниже.";
"add_signature" = "Подпись автора"; "add_signature" = "Подпись автора";
"contains_nsfw" = "Содержит NSFW-контент"; "contains_nsfw" = "Содержит NSFW-контент";
"nsfw_warning" = "Данный пост может содержать 18+ контент"; "nsfw_warning" = "Данный пост может содержать 18+ контент";
@ -791,6 +797,7 @@
/* Audios */ /* Audios */
"my" = "Моё";
"audios" = "Аудиозаписи"; "audios" = "Аудиозаписи";
"audio" = "Аудиозапись"; "audio" = "Аудиозапись";
"playlist" = "Плейлист"; "playlist" = "Плейлист";
@ -870,7 +877,7 @@
"remove_from_playlist" = "Удалить из плейлиста"; "remove_from_playlist" = "Удалить из плейлиста";
"delete_playlist" = "Удалить плейлист"; "delete_playlist" = "Удалить плейлист";
"playlist_cover" = "Обложка плейлиста"; "playlist_cover" = "Обложка плейлиста";
"playlists_user" = "Плейлисты польз."; "playlists_user" = "Плейлисты пользователя";
"playlists_club" = "Плейлисты группы"; "playlists_club" = "Плейлисты группы";
"change_cover" = "Сменить обложку"; "change_cover" = "Сменить обложку";
"playlist_cover" = "Обложка плейлиста"; "playlist_cover" = "Обложка плейлиста";
@ -1455,6 +1462,10 @@
"ffmpeg_not_installed" = "Не удалось обработать файл. Похоже, на сервере не установлен ffmpeg."; "ffmpeg_not_installed" = "Не удалось обработать файл. Похоже, на сервере не установлен ffmpeg.";
"too_many_or_to_lack" = "Слишком мало либо слишком много источников."; "too_many_or_to_lack" = "Слишком мало либо слишком много источников.";
"error_adding_source_regex" = "Ошибка добавления источника: некорректная ссылка.";
"error_adding_source_long" = "Ошибка добавления источника: слишком длинная ссылка.";
"error_adding_source_sus" = "Ошибка добавления источника: подозрительная ссылка.";
/* Admin actions */ /* Admin actions */
"login_as" = "Войти как $1"; "login_as" = "Войти как $1";
@ -1883,6 +1894,7 @@
/* Search */ /* Search */
"s_params" = "Параметры поиска";
"s_people" = "Пользователи"; "s_people" = "Пользователи";
"s_groups" = "Группы"; "s_groups" = "Группы";
"s_apps" = "Приложения"; "s_apps" = "Приложения";

View file

@ -1,7 +1,7 @@
.page_header { .page_header {
background-image: url('/themepack/midnight/0.0.2.9/resource/xheader.png') !important; background-image: url('/themepack/midnight/0.0.3.0/resource/xheader.png') !important;
} }
.page_custom_header { .page_custom_header {
background-image: url('/themepack/midnight/0.0.2.9/resource/xheader_custom.png') !important; background-image: url('/themepack/midnight/0.0.3.0/resource/xheader_custom.png') !important;
} }

View file

@ -9,7 +9,8 @@ html {
body, body,
#backdropDripper, #backdropDripper,
#standaloneCommentBox, #standaloneCommentBox,
.ovk-photo-view { .ovk-photo-view,
.articleView {
background-color: #0e0b1a; background-color: #0e0b1a;
color: #c6d2e8; color: #c6d2e8;
} }
@ -23,7 +24,8 @@ span,
.crp-entry--message---text, .crp-entry--message---text,
.messenger-app--messages---message .time, .messenger-app--messages---message .time,
.navigation-lang .link_new, .navigation-lang .link_new,
.tippy-box text { .tippy-box text,
.articleView_author > div > span > a {
color: #8b9ab5 !important; color: #8b9ab5 !important;
} }
@ -130,10 +132,19 @@ th,
.borderup, .borderup,
#tour, #tour,
#auth, #auth,
.ovk-photo-view { .ovk-photo-view,
.page_wrap_content_main .def_row_content,
.topGrayBlock,
.bigPlayer {
border-color: #2c2640 !important; border-color: #2c2640 !important;
} }
.post-upload,
.post-has-poll,
.post-has-note {
color: #777;
}
.tippy-box[data-theme~="vk"][data-placement^='top']>.tippy-arrow::before, .tippy-box[data-theme~="vk"][data-placement^='top']>.tippy-arrow::before,
.tippy-box[data-theme~="vk"][data-placement^='bottom']>.tippy-arrow::before { .tippy-box[data-theme~="vk"][data-placement^='bottom']>.tippy-arrow::before {
border-top-color: #1e1a2b; border-top-color: #1e1a2b;
@ -154,22 +165,28 @@ hr {
.messagebox-content-header, .messagebox-content-header,
.accent-box, .accent-box,
.button_search, .button_search,
.search_box_button { .header_navigation #search_box .search_box_button {
background-color: #383052; background-color: #383052;
} }
.header_navigation #search_box .search_box_button {
box-shadow: 0px 2px 0px 0px rgb(70, 63, 96) inset;
}
.search_option_name { .search_option_name {
background-color: #383052 !important; background-color: #383052 !important;
color: lightgrey !important; color: lightgrey !important;
} }
.tab:hover { .tab:hover,
.ntSelect:hover {
background-color: #40375e; background-color: #40375e;
} }
.menu_divider, .menu_divider,
.ovk-diag-action, .ovk-diag-action,
.minilink .counter { .minilink .counter,
.topGrayBlock {
background-color: #2c2640; background-color: #2c2640;
} }
@ -266,7 +283,8 @@ center[style="background: white;border: #DEDEDE solid 1px;"],
td.e, td.e,
tr.e, tr.e,
.playlistListView:hover, .playlistListView:hover,
.playlistListView .playlistCover { .playlistListView .playlistCover,
.photosInsert > div {
background-color: #231e33 !important; background-color: #231e33 !important;
} }
@ -295,11 +313,11 @@ tr.v,
} }
.content_title_expanded { .content_title_expanded {
background-image: url("/themepack/midnight/0.0.2.9/resource/flex_arrow_open.png") !important; background-image: url("/themepack/midnight/0.0.3.0/resource/flex_arrow_open.png") !important;
} }
.content_title_unexpanded { .content_title_unexpanded {
background-image: url("/themepack/midnight/0.0.2.9/resource/flex_arrow_shut.gif") !important; background-image: url("/themepack/midnight/0.0.3.0/resource/flex_arrow_shut.gif") !important;
} }
.ovk-video>.preview, .ovk-video>.preview,
@ -326,17 +344,17 @@ tr.h {
.page_yellowheader { .page_yellowheader {
color: #c6d2e8; color: #c6d2e8;
background-image: url("/themepack/midnight/0.0.2.9/resource/header_purple.png") !important; background-image: url("/themepack/midnight/0.0.3.0/resource/header_purple.png") !important;
background-color: #231f34; background-color: #231f34;
border-color: #231f34; border-color: #231f34;
} }
.page_header { .page_header {
background-image: url("/themepack/midnight/0.0.2.9/resource/header.png") !important; background-image: url("/themepack/midnight/0.0.3.0/resource/header.png") !important;
} }
.page_custom_header { .page_custom_header {
background-image: url("/themepack/midnight/0.0.2.9/resource/header_custom.png") !important; background-image: url("/themepack/midnight/0.0.3.0/resource/header_custom.png") !important;
} }
.page_yellowheader span, .page_yellowheader span,
@ -374,11 +392,11 @@ select,
} }
input[type="checkbox"] { input[type="checkbox"] {
background-image: url("/themepack/midnight/0.0.2.9/resource/checkbox.png") !important; background-image: url("/themepack/midnight/0.0.3.0/resource/checkbox.png") !important;
} }
input[type="radio"] { input[type="radio"] {
background-image: url("/themepack/midnight/0.0.2.9/resource/radio.png") !important; background-image: url("/themepack/midnight/0.0.3.0/resource/radio.png") !important;
} }
.header_navigation .link, .header_navigation .header_divider_stick { .header_navigation .link, .header_navigation .header_divider_stick {
@ -386,20 +404,20 @@ input[type="radio"] {
} }
.heart { .heart {
background-image: url("/themepack/midnight/0.0.2.9/resource/like.gif") !important; background-image: url("/themepack/midnight/0.0.3.0/resource/like.gif") !important;
} }
.pinned-mark, .pinned-mark,
.post-author .pin { .post-author .pin {
background-image: url("/themepack/midnight/0.0.2.9/resource/pin.png") !important; background-image: url("/themepack/midnight/0.0.3.0/resource/pin.png") !important;
} }
.repost-icon { .repost-icon {
background-image: url("/themepack/midnight/0.0.2.9/resource/published.gif") !important; background-image: url("/themepack/midnight/0.0.3.0/resource/published.gif") !important;
} }
.post-author .delete { .post-author .delete {
background-image: url("/themepack/midnight/0.0.2.9/resource/input_clear.gif") !important; background-image: url("/themepack/midnight/0.0.3.0/resource/input_clear.gif") !important;
} }
.user-alert { .user-alert {
@ -432,7 +450,7 @@ input[type="radio"] {
} }
#backdropEditor { #backdropEditor {
background-image: url("/themepack/midnight/0.0.2.9/resource/backdrop-editor.gif") !important; background-image: url("/themepack/midnight/0.0.3.0/resource/backdrop-editor.gif") !important;
border-color: #473e66 !important; border-color: #473e66 !important;
} }
@ -485,7 +503,8 @@ input[type="radio"] {
background: #19142D !important; background: #19142D !important;
} }
.audioEntry .performer a { .audioEntry .performer a,
.bigPlayer .paddingLayer .trackInfo a {
color: #a2a1a1 !important; color: #a2a1a1 !important;
} }
@ -591,3 +610,7 @@ ul {
background: #28223a; background: #28223a;
border: #2c2640 solid 1px; border: #2c2640 solid 1px;
} }
#backdropFilePicker {
margin: 15px !important;
}

View file

@ -1,5 +1,5 @@
id: midnight id: midnight
version: "0.0.2.9" version: "0.0.3.0"
openvk_version: 0 openvk_version: 0
enabled: 1 enabled: 1
metadata: metadata: