Compare commits

...

29 commits

Author SHA1 Message Date
celestora
ad77242f60
Merge branch 'master' into crop-avatar 2024-10-14 13:53:37 +03:00
veselcraft
bbef3a8518
feat(friends): delete leftovers 2024-09-18 22:07:17 +03:00
veselcraft
c5644a51d6
feat(friends): add ajax 2024-09-18 01:02:56 +03:00
veselcraft
4c78617a9c
feat(friends)!: reject request 2024-09-16 02:11:28 +03:00
89157a832b
fix: remove fartscroll 2024-09-07 18:29:44 +03:00
Artemka
91f30bd9d2
doc(README): Removed GitHub hard code from logo (#1126) 2024-07-26 16:38:55 +03:00
6013cd095e
ci(docker): optimise building of main image
Dependency libraries are loaded before copying the rest of the project files so dependencies may be cached during builds
2024-07-11 00:34:25 +03:00
97c577732b
fix(admin): use right function for hiding from global feed
also switched to n:attr here
2024-07-10 23:40:36 +03:00
188768594b
fix(photos): replace real with float
`real` is deprecated since PHP 8.0
2024-07-10 23:19:32 +03:00
a13d62e8fd
feat(groups): add option to enforce global feed exclusion (#1122) 2024-07-06 14:34:18 +03:00
Ry0
9d62bfc12e
fix audio.add (#1121)
* fix audio.add

* Fix settype to allow Null

* thx celestora <3

* Finaly, Tarhun
2024-07-01 22:43:56 +03:00
veselcraft
8786bd36fb
admin: fix chandlerlogs 2024-06-22 17:26:02 +03:00
veselcraft
3707ae0772
admin: add warning about broken longpool 2024-06-22 17:06:24 +03:00
veselcraft
bbbc8b7700
reports(moderators): reword the word 'delete' for mods after unfunny incident 2024-06-22 17:06:24 +03:00
veselcraft
4521d4a2f1
l18n: fix they/them pronouns in search and friendlists (after fucking nine months) 2024-06-22 17:06:23 +03:00
3349fa8b01
ci: another lowercase fix 2024-06-10 01:10:03 +03:00
8f76751f99
ci: fix action name 2024-06-10 00:53:35 +03:00
791da0f8df
ci: fix builds by turning repo name to lowercase while building 2024-06-10 00:50:18 +03:00
Artemka
3952d8437e
Removed some ovk.to hard code (#1117) 2024-06-08 19:18:12 +03:00
Evgeniy Khramov
9fd8b22a95
Fix feedback notification counter @layout.xml (#1114) 2024-05-17 12:38:44 +03:00
Jillian Österreich
ae689e1327
chore(theme-midnight): bump version to 0.0.2.9 2024-04-19 11:16:41 +03:00
marshallovski
61b3982349
fix(theme-midnight): change photo viewer bg color and "beautify" the stylesheet (#1107) 2024-04-19 11:12:41 +03:00
Jillian Österreich
4218e02f4b
chore: remove mentions of our older domain names
Closes GH-1099
2024-04-19 11:05:24 +03:00
celestora
2bdb4f03d0 feat(OAuth): add oauth flow 2024-03-30 21:51:38 +02:00
celestora
0b80c0a6a8 feat(API): implement token re-use mechanism 2024-03-30 12:59:10 +02:00
celestora
939ea30262 improvement(bootstrap): small compat fixes for WIN_NT on PHP 8.1 2024-03-30 12:29:50 +02:00
celestora
c4fb793333 improvement(API): fix inconsistencies in util.* + add chandler guid resolving funs 2024-03-27 22:38:35 +02:00
celestora
869712d73a
improvement(README): add system requirements (people ask for them a lot) 2024-02-19 13:41:38 +03:00
Jillian Österreich
eb95cef6d0
improve(locale-en): Correct spelling in some strings
minor spelling mistake 🌋
2024-02-05 12:23:31 +07:00
57 changed files with 988 additions and 416 deletions

2
.github/FUNDING.yml vendored
View file

@ -1 +1 @@
custom: "https://openvk.su/donate"
custom: "https://ovk.to/donate"

View file

@ -24,12 +24,18 @@ jobs:
id: buildx
uses: docker/setup-buildx-action@v2
- name: Change repository string to lowercase
id: repositorystring
uses: Entepotenz/change-string-case-action-min-dependencies@v1.1.0
with:
string: ${{ github.repository }}
- name: Log into registry
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
- name: Build cli image
run: |
IMAGE_NAME=ghcr.io/${{ github.repository }}/$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
@ -48,11 +54,17 @@ jobs:
id: buildx
uses: docker/setup-buildx-action@v2
- name: Change repository string to lowercase
id: repositorystring
uses: Entepotenz/change-string-case-action-min-dependencies@v1.1.0
with:
string: ${{ github.repository }}
- name: Log into registry
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
- name: Build apache image
run: |
IMAGE_NAME=ghcr.io/${{ github.repository }}/$BASE_IMAGE_NAME:$BASE_IMAGE_VERSION-apache
IMAGE_NAME=ghcr.io/${{ steps.repositorystring.outputs.lowercase }}/$BASE_IMAGE_NAME:$BASE_IMAGE_VERSION-apache
docker buildx build --platform linux/amd64,linux/arm64 -t $IMAGE_NAME . --push -f install/automated/docker/base-php-apache.Dockerfile --build-arg VERSION=$BASE_IMAGE_VERSION

View file

@ -36,12 +36,18 @@ jobs:
id: buildx
uses: docker/setup-buildx-action@v2
- name: Change repository string to lowercase
id: repositorystring
uses: Entepotenz/change-string-case-action-min-dependencies@v1.1.0
with:
string: ${{ github.repository }}
- name: Log into registry
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
- name: Build base image
run: |
IMAGE_ID=ghcr.io/${{ github.repository }}/$BASE_IMAGE_NAME
IMAGE_ID=ghcr.io/${{ steps.repositorystring.outputs.lowercase }}/$BASE_IMAGE_NAME
IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')
VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')
[[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')
@ -49,16 +55,16 @@ jobs:
echo IMAGE_ID=$IMAGE_ID
echo VERSION=$VERSION
docker buildx build --platform linux/amd64,linux/arm64 -t $IMAGE_ID:$VERSION . --push -f install/automated/docker/openvk.Dockerfile --build-arg GITREPO=${{ github.repository }}
docker buildx build --platform linux/amd64,linux/arm64 -t $IMAGE_ID:$VERSION . --push -f install/automated/docker/openvk.Dockerfile --build-arg GITREPO=${{ steps.repositorystring.outputs.lowercase }}
- name: Build MariaDB primary image
run: |
IMAGE_NAME=ghcr.io/${{ github.repository }}/$DB_IMAGE_NAME:$DB_VERSION-primary
IMAGE_NAME=ghcr.io/${{ steps.repositorystring.outputs.lowercase }}/$DB_IMAGE_NAME:$DB_VERSION-primary
docker buildx build --platform linux/amd64,linux/arm64 -t $IMAGE_NAME . --push -f install/automated/docker/mariadb-primary.Dockerfile --build-arg VERSION=$DB_VERSION
- name: Build MariaDB event image
run: |
IMAGE_NAME=ghcr.io/${{ github.repository }}/$EVENT_IMAGE_NAME:$DB_VERSION-eventdb
IMAGE_NAME=ghcr.io/${{ steps.repositorystring.outputs.lowercase }}/$EVENT_IMAGE_NAME:$DB_VERSION-eventdb
docker buildx build --platform linux/amd64,linux/arm64 -t $IMAGE_NAME . --push -f install/automated/docker/mariadb-eventdb.Dockerfile --build-arg VERSION=$DB_VERSION

View file

@ -12,7 +12,7 @@
<tr>
<td class="float-center" align="center" valign="top">
<center>
Добро пожаловать в OpenVK! Приятного времяприпровождения, надеюсь вам понравится.<br><br>Если появились вопросы, касаемые нашего сайта, пишите <a href="https://openvk.su/support?act=new">сюда</a>
Добро пожаловать в OpenVK! Приятного времяприпровождения, надеюсь вам понравится.<br><br>Если появились вопросы, касаемые нашего сайта, пишите <a href="https://ovk.to/support?act=new">сюда</a>
</center>
</td>
</tr>

View file

@ -1,4 +1,4 @@
# <img align="right" src="https://github.com/openvk/openvk/raw/master/Web/static/img/logo_shadow.png" alt="openvk" title="openvk" width="15%">OpenVK
# <img align="right" src="/Web/static/img/logo_shadow.png" alt="openvk" title="openvk" width="15%">OpenVK
_[Русский](README_RU.md)_
@ -6,7 +6,7 @@ _[Русский](README_RU.md)_
VKontakte belongs to Pavel Durov and VK Group.
To be honest, we don't know whether if it even works. However, this version is maintained and we will be happy to accept your bugreports [in our bug tracker](https://github.com/openvk/openvk/projects/1). You should also be able to submit them using [ticketing system](https://openvk.su/support?act=new) (you will need an OpenVK account for this).
To be honest, we don't know whether if it even works. However, this version is maintained and we will be happy to accept your bugreports [in our bug tracker](https://github.com/openvk/openvk/projects/1). You should also be able to submit them using [ticketing system](https://ovk.to/support?act=new) (you will need an OpenVK account for this).
## When's the release?
@ -26,6 +26,14 @@ However, OVK makes use of Chandler Application Server. This software requires ex
If you want, you can add your instance to the list above so that people can register there.
### System requirements
Here is our minimum hardware recommendation:
* **CPU: Recent** (AMD Zen2 or equivalent) quad-core 2GHz+ CPU
* **RAM:** At least 2GB RAM (we recommend 6GB or 8GB for OpenVK with Kafka)
* **Minimum database space:** 10GB
### Installation procedure
1. Install PHP 7.4, web-server, Composer, Node.js, Yarn and [Chandler](https://github.com/openvk/chandler)
@ -66,7 +74,7 @@ Once you are done, you can login as a system administrator on the network itself
* **Password**: `admin`
* It is recommended to change the password of the built-in account or disable it.
💡 Confused? Full installation walkthrough is available [here](https://docs.openvk.uk/openvk_engine/centos8_installation/) (CentOS 8 [and](https://almalinux.org/) [family](https://yum.oracle.com/oracle-linux-isos.html)).
💡 Confused? Full installation walkthrough is available [here](https://docs.ovk.to/openvk_engine/centos8_installation/) (CentOS 8 [and](https://almalinux.org/) [family](https://yum.oracle.com/oracle-linux-isos.html)).
### Looking for Docker or Kubernetes deployment?
See `install/automated/docker/README.md` and `install/automated/kubernetes/README.md` for Docker and Kubernetes deployment instructions.
@ -80,7 +88,7 @@ It depends. You can keep the sources to yourself if you do not plan to distribut
You may reach out to us via:
* [Bug Tracker](https://github.com/openvk/openvk/projects/1)
* [Ticketing System](https://openvk.su/support?act=new)
* [Ticketing System](https://ovk.to/support?act=new)
* Telegram Chat: Go to [our channel](https://t.me/openvkenglish) and open discussion in our channel menu.
* [Reddit](https://www.reddit.com/r/openvk/)
* [GitHub Discussions](https://github.com/openvk/openvk/discussions)

View file

@ -1,4 +1,4 @@
# <img align="right" src="https://github.com/openvk/openvk/raw/master/Web/static/img/logo_shadow.png" alt="openvk" title="openvk" width="15%">OpenVK
# <img align="right" src="/Web/static/img/logo_shadow.png" alt="openvk" title="openvk" width="15%">OpenVK
_[English](README.md)_
@ -6,7 +6,7 @@ _[English](README.md)_
ВКонтакте принадлежит Павлу Дурову и VK Group.
Честно говоря, мы даже не знаем, работает ли она вообще. Однако, эта версия поддерживается, и мы будем рады принять ваши сообщения об ошибках [в нашем баг-трекере](https://github.com/openvk/openvk/projects/1). Вы также можете отправлять их через [вкладку "Помощь"](https://openvk.su/support?act=new) (для этого вам понадобится учетная запись OpenVK).
Честно говоря, мы даже не знаем, работает ли она вообще. Однако, эта версия поддерживается, и мы будем рады принять ваши сообщения об ошибках [в нашем баг-трекере](https://github.com/openvk/openvk/projects/1). Вы также можете отправлять их через [вкладку "Помощь"](https://ovk.to/support?act=new) (для этого вам понадобится учетная запись OpenVK).
## Когда выйдет релизная версия?
@ -66,7 +66,7 @@ ln -s /path/to/chandler/extensions/available/openvk /path/to/chandler/extensions
* **Пароль**: `admin`
* Перед использованием встроенной учетной записи рекомендуется сменить пароль или отключить её.
💡Запутались? Полное руководство по установке доступно [здесь](https://docs.openvk.uk/openvk_engine/centos8_installation/) (CentOS 8 [и](https://almalinux.org/ru/) [семейство](https://yum.oracle.com/oracle-linux-isos.html)).
💡Запутались? Полное руководство по установке доступно [здесь](https://docs.ovk.to/openvk_engine/centos8_installation/) (CentOS 8 [и](https://almalinux.org/ru/) [семейство](https://yum.oracle.com/oracle-linux-isos.html)).
# Установка в Docker/Kubernetes
Подробные иструкции можно найти в `install/automated/docker/README.md` и `install/automated/kubernetes/README.md` соответственно.
@ -80,7 +80,7 @@ ln -s /path/to/chandler/extensions/available/openvk /path/to/chandler/extensions
Вы можете связаться с нами через:
* [Баг-трекер](https://github.com/openvk/openvk/projects/1)
* [Помощь в OVK](https://openvk.su/support?act=new)
* [Помощь в OVK](https://ovk.to/support?act=new)
* Telegram-чат: Перейдите на [наш канал](https://t.me/openvk) и откройте обсуждение в меню нашего канала.
* [Reddit](https://www.reddit.com/r/openvk/)
* [GitHub Discussions](https://github.com/openvk/openvk/discussions)

View file

@ -1,8 +1,11 @@
<?php declare(strict_types=1);
namespace openvk\ServiceAPI;
use openvk\Web\Models\Entities\APIToken;
use openvk\Web\Models\Entities\User;
use openvk\Web\Models\Repositories\APITokens;
use openvk\Web\Models\Repositories\Applications;
use WhichBrowser;
class Apps implements Handler
{
@ -89,4 +92,25 @@ class Apps implements Handler
$app->withdrawCoins();
$resolve($coins);
}
function getRegularToken(string $clientName, bool $acceptsStale, callable $resolve, callable $reject): void
{
$token = NULL;
$stale = true;
if($acceptsStale)
$token = (new APITokens)->getStaleByUser($this->user->getId(), $clientName);
if(is_null($token)) {
$stale = false;
$token = new APIToken;
$token->setUser($this->user);
$token->setPlatform($clientName ?? (new WhichBrowser\Parser(getallheaders()))->toString());
$token->save();
}
$resolve([
'is_stale' => $stale,
'token' => $token->getFormattedToken(),
]);
}
}

View file

@ -147,7 +147,7 @@ final class Friends extends VKAPIRequestHandler
return $response;
}
function getRequests(string $fields = "", int $offset = 0, int $count = 100, int $extended = 0): object
function getRequests(string $fields = "", int $out = 0, int $offset = 0, int $count = 100, int $extended = 0): object
{
if ($count >= 1000)
$this->fail(100, "One of the required parameters was not passed or is invalid.");
@ -158,9 +158,18 @@ final class Friends extends VKAPIRequestHandler
$offset++;
$followers = [];
foreach($this->getUser()->getFollowers($offset, $count) as $follower) {
$followers[$i] = $follower->getId();
$i++;
if ($out != 0) {
foreach($this->getUser()->getFollowers($offset, $count) as $follower) {
$followers[$i] = $follower->getId();
$i++;
}
}
else
{
foreach($this->getUser()->getRequests($offset, $count) as $follower) {
$followers[$i] = $follower->getId();
$i++;
}
}
$response = $followers;

View file

@ -347,7 +347,10 @@ final class Groups extends VKAPIRequestHandler
!empty($topics) ? $club->setEveryone_Can_Create_Topics($topics) : NULL;
!empty($adminlist) ? $club->setAdministrators_List_Display($adminlist) : NULL;
!empty($topicsAboveWall) ? $club->setDisplay_Topics_Above_Wall($topicsAboveWall) : NULL;
!empty($hideFromGlobalFeed) ? $club->setHide_From_Global_Feed($hideFromGlobalFeed) : NULL;
if (!$club->isHidingFromGlobalFeedEnforced()) {
!empty($hideFromGlobalFeed) ? $club->setHide_From_Global_Feed($hideFromGlobalFeed) : NULL;
}
in_array($audio, [0, 1]) ? $club->setEveryone_can_upload_audios($audio) : NULL;

View file

@ -246,6 +246,9 @@ final class Users extends VKAPIRequestHandler
"notes_count" => (new Notes)->getUserNotesCount($usr)
];
break;
case "guid":
$response[$i]->guid = $usr->getChandlerGUID();
break;
}
}

View file

@ -22,7 +22,7 @@ final class Utils extends VKAPIRequestHandler
"object_id" => (int) substr($screen_name, strlen("club")),
"type" => "group"
];
}
} else $this->fail(104, "Not found");
} else {
$user = (new Users)->getByShortURL($screen_name);
if($user) {
@ -40,7 +40,16 @@ final class Utils extends VKAPIRequestHandler
];
}
return (object) [];
$this->fail(104, "Not found");
}
}
function resolveGuid(string $guid): object
{
$user = (new Users)->getByChandlerUserId($guid);
if (is_null($user))
$this->fail(104, "Not found");
return $user->toVkApiStruct($this->getUser());
}
}

View file

@ -5,7 +5,7 @@ exceptions. It is still a work-in-progress functionality.
**Note**: requests to API are routed through
openvk.Web.Presenters.VKAPIPresenter, this dir contains only handlers.
[Documentation for API clients](https://docs.openvk.uk/openvk_engine/api/description/)
[Documentation for API clients](https://docs.ovk.to/openvk_engine/api/description/)
## Implementing API methods

View file

@ -152,6 +152,11 @@ class Club extends RowModel
return (bool) $this->getRecord()->hide_from_global_feed;
}
function isHidingFromGlobalFeedEnforced(): bool
{
return (bool) $this->getRecord()->enforce_hiding_from_global_feed;
}
function getType(): int
{
return $this->getRecord()->type;

View file

@ -114,7 +114,7 @@ class Photo extends Media
return true;
}
function crop(real $left, real $top, real $width, real $height): void
function crop(float $left, float $top, float $width, float $height): void
{
if(isset($this->changes["hash"]))
$hash = $this->changes["hash"];

View file

@ -39,4 +39,25 @@ trait TSubscribable
$sub->delete();
return false;
}
function changeFlags(User $user, int $flags, bool $reverse): bool
{
$ctx = DatabaseConnection::i()->getContext();
$data = [
"follower" => $reverse ? $this->getId() : $user->getId(),
"model" => static::class,
"target" => $reverse ? $user->getId() : $this->getId(),
];
$sub = $ctx->table("subscriptions")->where($data);
bdump($data);
if (!$sub)
return false;
$sub->update([
'flags' => $flags
]);
return true;
}
}

View file

@ -592,6 +592,16 @@ class User extends RowModel
return $this->_abstractRelationCount("get-followers");
}
function getRequests(int $page = 1, int $limit = 6): \Traversable
{
return $this->_abstractRelationGenerator("get-requests", $page, $limit);
}
function getRequestsCount(): int
{
return $this->_abstractRelationCount("get-requests");
}
function getSubscriptions(int $page = 1, int $limit = 6): \Traversable
{
return $this->_abstractRelationGenerator("get-subscriptions-user", $page, $limit);

View file

@ -23,4 +23,13 @@ class APITokens extends Repository
return $token;
}
function getStaleByUser(int $userId, string $platform, bool $withRevoked = false): ?APIToken
{
return $this->toEntity($this->table->where([
'user' => $userId,
'platform' => $platform,
'deleted' => $withRevoked,
])->fetch());
}
}

View file

@ -44,9 +44,14 @@ class Users
return $alias->getUser();
}
function getByChandlerUserId(string $cid): ?User
{
return $this->toUser($this->users->where("user", $cid)->fetch());
}
function getByChandlerUser(?ChandlerUser $user): ?User
{
return $user ? $this->toUser($this->users->where("user", $user->getId())->fetch()) : NULL;
return $user ? $this->getByChandlerUserId($user->getId()) : NULL;
}
function find(string $query, array $pars = [], string $sort = "id DESC"): Util\EntityStream

View file

@ -1,5 +1,5 @@
(SELECT DISTINCT(follower) AS __id FROM
(SELECT follower FROM subscriptions WHERE target=? AND model="openvk\\Web\\Models\\Entities\\User") u0
(SELECT follower, flags FROM subscriptions WHERE target=? AND model="openvk\\Web\\Models\\Entities\\User") u0
LEFT JOIN
(SELECT target FROM subscriptions WHERE follower=? AND model="openvk\\Web\\Models\\Entities\\User") u1
ON u0.follower = u1.target WHERE u1.target IS NULL) u2

View file

@ -0,0 +1,6 @@
(SELECT DISTINCT(follower) AS __id FROM
(SELECT follower FROM subscriptions WHERE target=? AND flags=0 AND model="openvk\\Web\\Models\\Entities\\User") u0
LEFT JOIN
(SELECT target FROM subscriptions WHERE follower=? AND flags=0 AND model="openvk\\Web\\Models\\Entities\\User") u1
ON u0.follower = u1.target WHERE u1.target IS NULL) u2
INNER JOIN profiles ON profiles.id = u2.__id

View file

@ -145,6 +145,6 @@ final class AboutPresenter extends OpenVKPresenter
function renderDev(): void
{
$this->redirect("https://docs.openvk.uk/");
$this->redirect("https://docs.ovk.to/");
}
}

View file

@ -49,6 +49,13 @@ final class AdminPresenter extends OpenVKPresenter
$this->flash("warn", tr("admin_commerce_disabled"), tr("admin_commerce_disabled_desc"));
}
private function warnIfLongpoolBroken(): void
{
bdump(is_writable(CHANDLER_ROOT . '/tmp/events.bin'));
if(file_exists(CHANDLER_ROOT . '/tmp/events.bin') == false || is_writable(CHANDLER_ROOT . '/tmp/events.bin') == false)
$this->flash("warn", tr("admin_longpool_broken"), tr("admin_longpool_broken_desc", CHANDLER_ROOT . '/tmp/events.bin'));
}
private function searchResults(object $repo, &$count)
{
$query = $this->queryParam("q") ?? "";
@ -76,7 +83,7 @@ final class AdminPresenter extends OpenVKPresenter
function renderIndex(): void
{
$this->warnIfLongpoolBroken();
}
function renderUsers(): void
@ -154,6 +161,7 @@ final class AdminPresenter extends OpenVKPresenter
$club->setShortCode($this->postParam("shortcode"));
$club->setVerified(empty($this->postParam("verify") ? 0 : 1));
$club->setHide_From_Global_Feed(empty($this->postParam("hide_from_global_feed") ? 0 : 1));
$club->setEnforce_Hiding_From_Global_Feed(empty($this->postParam("enforce_hiding_from_global_feed") ? 0 : 1));
$club->save();
break;
case "ban":
@ -681,7 +689,8 @@ final class AdminPresenter extends OpenVKPresenter
$this->template->obj_type = $obj_type;
}
$this->template->logs = (new Logs)->search($filter);
$logs = iterator_to_array((new Logs)->search($filter));
$this->template->logs = $logs;
$this->template->object_types = (new Logs)->getTypes();
}
}

View file

@ -233,7 +233,10 @@ final class GroupPresenter extends OpenVKPresenter
$club->setEveryone_Can_Create_Topics(empty($this->postParam("everyone_can_create_topics")) ? 0 : 1);
$club->setDisplay_Topics_Above_Wall(empty($this->postParam("display_topics_above_wall")) ? 0 : 1);
$club->setEveryone_can_upload_audios(empty($this->postParam("upload_audios")) ? 0 : 1);
$club->setHide_From_Global_Feed(empty($this->postParam("hide_from_global_feed")) ? 0 : 1);
if (!$club->isHidingFromGlobalFeedEnforced()) {
$club->setHide_From_Global_Feed(empty($this->postParam("hide_from_global_feed") ? 0 : 1));
}
$website = $this->postParam("website") ?? "";
if(empty($website))

View file

@ -329,9 +329,12 @@ final class UserPresenter extends OpenVKPresenter
$user = $this->users->get((int) $this->postParam("id"));
if(!$user) exit("Invalid state");
$user->toggleSubscription($this->user->identity);
if ($this->postParam("act") == "rej")
$user->changeFlags($this->user->identity, 0b10000000, true);
else
$user->toggleSubscription($this->user->identity);
$this->redirect($user->getURL());
$this->redirect($_SERVER['HTTP_REFERER']);
}
function renderSetAvatar() {

View file

@ -234,8 +234,14 @@ final class VKAPIPresenter extends OpenVKPresenter
}
try {
settype($val, $parameter->getType()->getName());
$params[] = $val;
// Проверка типа параметра
$type = $parameter->getType();
if (($type && !$type->isBuiltin()) || is_null($val)) {
$params[] = $val;
} else {
settype($val, $parameter->getType()->getName());
$params[] = $val;
}
} catch (\Throwable $e) {
// Just ignore the exception, since
// some args are intended for internal use
@ -286,17 +292,31 @@ final class VKAPIPresenter extends OpenVKPresenter
$this->fail(28, "Invalid 2FA code", "internal", "acquireToken");
}
$platform = $this->requestParam("client_name");
$token = NULL;
$tokenIsStale = true;
$platform = $this->requestParam("client_name");
$acceptsStale = $this->requestParam("accepts_stale");
if($acceptsStale == "1") {
if(is_null($platform))
$this->fail(101, "accepts_stale can only be used with explicitly set client_name", "internal", "acquireToken");
$token = new APIToken;
$token->setUser($user);
$token->setPlatform($platform ?? (new WhichBrowser\Parser(getallheaders()))->toString());
$token->save();
$token = (new APITokens)->getStaleByUser($uId, $platform);
}
if(is_null($token)) {
$tokenIsStale = false;
$token = new APIToken;
$token->setUser($user);
$token->setPlatform($platform ?? (new WhichBrowser\Parser(getallheaders()))->toString());
$token->save();
}
$payload = json_encode([
"access_token" => $token->getFormattedToken(),
"expires_in" => 0,
"user_id" => $uId,
"is_stale" => $tokenIsStale,
]);
$size = strlen($payload);
@ -304,4 +324,42 @@ final class VKAPIPresenter extends OpenVKPresenter
header("Content-Length: $size");
exit($payload);
}
function renderOAuthLogin() {
$this->assertUserLoggedIn();
$client = $this->queryParam("client_name");
$postmsg = $this->queryParam("prefers_postMessage") ?? '0';
$stale = $this->queryParam("accepts_stale") ?? '0';
$origin = NULL;
$url = $this->queryParam("redirect_uri");
if(is_null($url) || is_null($client))
exit("<b>Error:</b> redirect_uri and client_name params are required.");
if($url != "about:blank") {
if(!filter_var($url, FILTER_VALIDATE_URL))
exit("<b>Error:</b> Invalid URL passed to redirect_uri.");
$parsedUrl = (object) parse_url($url);
if($parsedUrl->scheme != 'https' && $parsedUrl->scheme != 'http')
exit("<b>Error:</b> redirect_uri should either point to about:blank or to a web resource.");
$origin = "$parsedUrl->scheme://$parsedUrl->host";
if(!is_null($parsedUrl->port ?? NULL))
$origin .= ":$parsedUrl->port";
$url .= strpos($url, '?') === false ? '?' : '&';
} else {
$url .= "#";
if($postmsg == '1') {
exit("<b>Error:</b> prefers_postMessage can only be set if redirect_uri is not about:blank");
}
}
$this->template->clientName = $client;
$this->template->usePostMessage = $postmsg == '1';
$this->template->acceptsStale = $stale == '1';
$this->template->origin = $origin;
$this->template->redirectUri = $url;
}
}

View file

@ -180,9 +180,9 @@
<a href="/edit" class="link edit-button">{_edit_button}</a>
<a href="{$thisUser->getURL()}" class="link" title="{_my_page} [Alt+Shift+.]" accesskey=".">{_my_page}</a>
<a href="/friends{$thisUser->getId()}" class="link">{_my_friends}
<object type="internal/link" n:if="$thisUser->getFollowersCount() > 0">
<object type="internal/link" n:if="$thisUser->getRequestsCount() > 0">
<a href="/friends{$thisUser->getId()}?act=incoming" class="linkunderline">
(<b>{$thisUser->getFollowersCount()}</b>)
(<b>{$thisUser->getRequestsCount()}</b>)
</a>
</object>
</a>
@ -198,9 +198,9 @@
<a n:if="$thisUser->getLeftMenuItemStatus('groups')" href="/groups{$thisUser->getId()}" class="link">{_my_groups}</a>
<a n:if="$thisUser->getLeftMenuItemStatus('news')" href="/feed" class="link" title="{_my_feed} [Alt+Shift+,]" accesskey=",">{_my_feed}</a>
<a href="/notifications" class="link" title="{_my_feedback} [Alt+Shift+N]" accesskey="n">{_my_feedback}
{if $thisUser->getNotificationsCount() > 0}
<object type="internal/link" n:if="$thisUser->getNotificationsCount() > 0">
(<b>{$thisUser->getNotificationsCount()}</b>)
{/if}
</object>
</a>
<a n:if="$thisUser->getLeftMenuItemStatus('apps')" href="/apps?act=installed" class="link">{_my_apps}</a>
<a href="/settings" class="link">{_my_settings}</a>
@ -405,13 +405,6 @@
{script "js/al_notifs.js"}
{/ifset}
{if OPENVK_ROOT_CONF['openvk']['preferences']['bellsAndWhistles']['fartscroll']}
<script src="https://unpkg.com/fartscroll@1.0.0/fartscroll.js"></script>
<script>
fartscroll(400);
</script>
{/if}
<script>bsdnHydrate();</script>
<script n:if="OPENVK_ROOT_CONF['openvk']['telemetry']['plausible']['enable']" async defer data-domain="{php echo OPENVK_ROOT_CONF['openvk']['telemetry']['plausible']['domain']}" src="{php echo OPENVK_ROOT_CONF['openvk']['telemetry']['plausible']['server']}js/plausible.js"></script>

View file

@ -49,7 +49,7 @@
{include description, x => $dat}
{/ifset}
</td>
<td n:ifset="actions" valign="top" class="action_links" style="width: 150px;">
<td n:ifset="actions" valign="top" class="action_links" style="min-width: 150px;">
{include actions, x => $dat}
</td>
</tr>

View file

@ -255,17 +255,6 @@
Disabled
</td>
</tr>
<tr>
<td class="e">
Fartscroll
</td>
<td class="v">
{php echo OPENVK_ROOT_CONF["openvk"]["preferences"]["bellsAndWhistles"]["fartscroll"] ? "Enabled" : "Disabled"}
</td>
<td class="v">
Disabled
</td>
</tr>
<tr>
<td class="e">
NDA Test Label

View file

@ -58,13 +58,17 @@
</div>
<br/>
<div class="group">
<input class="toggle-large" type="checkbox" id="verify" name="verify" value="1" {if $club->isVerified()} checked {/if} />
<input class="toggle-large" type="checkbox" id="verify" name="verify" value="1" n:attr="checked => $club->isVerified()" />
<label for="verify">{_admin_verification}</label>
</div>
<div class="group">
<input class="toggle-large" type="checkbox" id="hide_from_global_feed" name="hide_from_global_feed" value="1" {if $club->isHideFromGlobalFeedEnabled()} checked {/if} />
<input class="toggle-large" type="checkbox" id="hide_from_global_feed" name="hide_from_global_feed" value="1" n:attr="checked => $club->isHideFromGlobalFeedEnabled()" />
<label for="hide_from_global_feed">{_admin_club_excludeglobalfeed}</label>
</div>
<div class="group">
<input class="toggle-large" type="checkbox" id="enforce_hiding_from_global_feed" name="enforce_hiding_from_global_feed" value="1" n:attr="checked => $club->isHidingFromGlobalFeedEnforced()" />
<label for="enforce_hiding_from_global_feed">{_admin_club_enforceexcludeglobalfeed}</label>
</div>
<hr/>
<div class="buttons-container">
<div class="buttons">

View file

@ -83,7 +83,7 @@
<option value="0" n:attr="selected => $club->getWallType() == 0" /> {_group_closed_post}</option>
<select>
<input type="checkbox" name="hide_from_global_feed" value="1" n:attr="checked => $club->isHideFromGlobalFeedEnabled()" /> {_group_hide_from_global_feed}
<input type="checkbox" name="hide_from_global_feed" value="1" n:attr="checked => $club->isHideFromGlobalFeedEnabled(), disabled => $club->isHidingFromGlobalFeedEnforced()" /> {_group_hide_from_global_feed}
</td>
</tr>
<tr>

View file

@ -54,8 +54,8 @@
<table>
<tbody>
<tr>
<td width="120" valign="top"><span class="nobold">{_gender}: </span></td>
<td>{$user->isFemale() ? tr("female"): tr("male")}</td>
<td width="120" valign="top"><span class="nobold">{_pronouns}: </span></td>
<td>{$x->isFemale() ? tr("female") : ($x->isNeutral() ? tr("neutral") : tr("male"))}</td>
</tr>
<tr>
<td width="120" valign="top"><span class="nobold">{_registration_date}: </span></td>

View file

@ -23,7 +23,7 @@
<form n:if="$report->getContentType() != 'group'" action="/admin/reportAction{$report->getId()}" method="post">
<input type="hidden" name="hash" value="{$csrfToken}"/>
<input type="submit" name="ban" value="{_ban_user_action}" class="button">
<input n:if="$report->getContentType() !== 'user'" type="submit" name="delete" value="{_delete}" class="button">
<input n:if="$report->getContentType() !== 'user'" type="submit" name="delete" value="{_delete_content}" class="button">
<input type="submit" name="ignore" value="{_ignore_report}" class="button">
</form>
<form n:if="$report->getContentType() == 'group'" action="/admin/reportAction{$report->getId()}" method="post">

View file

@ -4,11 +4,14 @@
{var $act = $_GET["act"] ?? "friends"}
{if $act == "incoming"}
{var $iterator = iterator_to_array($user->getFollowers($page))}
{var $count = $user->getFollowersCount()}
{var $iterator = iterator_to_array($user->getRequests($page))}
{var $count = $user->getRequestsCount()}
{elseif $act == "outcoming"}
{var $iterator = iterator_to_array($user->getSubscriptions($page))}
{var $count = $user->getSubscriptionsCount()}
{elseif $act == "followers"}
{var $iterator = iterator_to_array($user->getFollowers($page))}
{var $count = $user->getFollowersCount()}
{elseif $act == "online"}
{var $iterator = iterator_to_array($user->getFriendsOnline($page))}
{var $count = $user->getFriendsOnlineCount()}
@ -22,6 +25,8 @@
{_incoming_req}
{elseif $act == "outcoming"}
{_outcoming_req}
{elseif $act == "followers"}
{_followers}
{elseif $act == "online"}
{_friends_online}
{else}
@ -38,6 +43,8 @@
{_incoming_req}
{elseif $act == "outcoming"}
{_outcoming_req}
{elseif $act == "followers"}
{_followers}
{elseif $act == "online"}
{_friends_online}
{else}
@ -53,18 +60,23 @@
<div n:attr="id => ($act === 'online' ? 'activetabs' : 'ki')" class="tab">
<a n:attr="id => ($act === 'online' ? 'act_tab_a' : 'ki')" href="?act=online">{_online}</a>
</div>
<div n:if="!is_null($thisUser) && $user->getId() === $thisUser->getId()" n:attr="id => ($act === 'incoming' || $act === 'outcoming' ? 'activetabs' : 'ki')" class="tab">
<a n:attr="id => ($act === 'incoming' || $act === 'outcoming' ? 'act_tab_a' : 'ki')" href="?act=incoming">{_req}</a>
<div n:if="!is_null($thisUser) && $user->getId() === $thisUser->getId()" n:attr="id => ($act === 'incoming' || $act === 'followers' || $act === 'outcoming' ? 'activetabs' : 'ki')" class="tab">
<a n:attr="id => ($act === 'incoming' || $act === 'followers' || $act === 'outcoming' ? 'act_tab_a' : 'ki')" href="?act=incoming">{_req}</a>
</div>
{/block}
{block size}
<div n:if="$act === 'incoming' || $act === 'outcoming'" class="mb_tabs">
<div n:if="$act === 'incoming' || $act === 'followers' || $act === 'outcoming'" class="mb_tabs">
<div n:attr="id => ($act === 'incoming' ? 'active' : 'ki')" class="mb_tab">
<div>
<a href="?act=incoming">{_incoming_req}</a>
</div>
</div>
<div n:attr="id => ($act === 'followers' ? 'active' : 'ki')" class="mb_tab">
<div>
<a href="?act=followers">{_followers}</a>
</div>
</div>
<div n:attr="id => ($act === 'outcoming' ? 'active' : 'ki')" class="mb_tab">
<div>
<a href="?act=outcoming">{_outcoming_req}</a>
@ -78,6 +90,8 @@
{tr("req", $count)}
{elseif $act == "outcoming"}
{tr("req", $count)}
{elseif $act == "followers"}
{tr("followers", $count)}
{elseif $act == "online"}
{tr("friends_list_online", $count)}
{else}
@ -112,8 +126,8 @@
<table>
<tbody>
<tr>
<td width="120" valign="top"><span class="nobold">{_gender}: </span></td>
<td>{$x->isFemale() ? tr("female") : tr("male")}</td>
<td width="120" valign="top"><span class="nobold">{_pronouns}: </span></td>
<td>{$x->isFemale() ? tr("female") : ($x->isNeutral() ? tr("neutral") : tr("male"))}</td>
</tr>
<tr>
<td width="120" valign="top"><span class="nobold">{_relationship}:</span></td>
@ -131,21 +145,29 @@
{if ($x->getId() !== $thisUser->getId()) && ($thisUser->getId() === $user->getId())}
{var $subStatus = $x->getSubscriptionStatus($thisUser)}
{if $subStatus === 0}
<form action="/setSub/user" method="post" class="profile_link_form">
<form action="/setSub/user" method="post" class="profile_link_form" id="_submitUserSubscriptionAction">
<input type="hidden" name="act" value="add" />
<input type="hidden" name="id" value="{$x->getId()}" />
<input type="hidden" name="hash" value="{$csrfToken}" />
<input type="submit" class="profile_link" value="{_friends_add}" />
</form>
{elseif $subStatus === 1}
<form action="/setSub/user" method="post" class="profile_link_form">
<form action="/setSub/user" method="post" class="profile_link_form" id="_submitUserSubscriptionAction">
<input type="hidden" name="act" value="add" />
<input type="hidden" name="id" value="{$x->getId()}" />
<input type="hidden" name="hash" value="{$csrfToken}" />
<input type="submit" class="profile_link" value="{_friends_accept}" />
</form>
{if $act !== 'followers'}
<form action="/setSub/user" method="post" class="profile_link_form" id="_submitUserSubscriptionAction">
<input type="hidden" name="act" value="rej" />
<input type="hidden" name="id" value="{$x->getId()}" />
<input type="hidden" name="hash" value="{$csrfToken}" />
<input type="submit" class="profile_link" value="{_friends_leave_in_flw}" />
</form>
{/if}
{elseif $subStatus === 2}
<form action="/setSub/user" method="post" class="profile_link_form">
<form action="/setSub/user" method="post" class="profile_link_form" id="_submitUserSubscriptionAction">
<input type="hidden" name="act" value="rem" />
<input type="hidden" name="id" value="{$x->getId()}" />
<input type="hidden" name="hash" value="{$csrfToken}" />
@ -153,7 +175,7 @@
</form>
{elseif $subStatus === 3}
<a href="/im?sel={$x->getId()}" class="profile_link">{_send_message}</a>
<form action="/setSub/user" method="post" class="profile_link_form">
<form action="/setSub/user" method="post" class="profile_link_form" id="_submitUserSubscriptionAction">
<input type="hidden" name="act" value="rem" />
<input type="hidden" name="id" value="{$x->getId()}" />
<input type="hidden" name="hash" value="{$csrfToken}" />

View file

@ -0,0 +1,193 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Получение доступа | OpenVK</title>
<style>
body {
margin: 0;
font-family: sans-serif;
background-color: #ebedf0;
}
header {
background-color: #fff;
box-shadow: 0 0 10px #d4d6d8;
padding: 13px 0;
margin-bottom: 12px;
}
header > div {
display: flex;
width: 100%;
max-width: 620px;
margin: auto;
align-items: center;
justify-content: space-between;
}
#ovkUser a:not(#pfpLink) {
color: #000;
text-decoration: none;
font-weight: 600;
font-size: 14px;
margin-right: 4px;
}
#ovkUser img {
width: 32px;
height: 32px;
border-radius: 100%;
vertical-align: middle;
object-fit: cover;
}
#ovkLogo a {
display: flex;
text-decoration: none;
color: #fff;
background: #606060;
width: 28px;
height: 28px;
justify-content: center;
align-items: center;
font-size: 21px;
font-weight: 600;
border-radius: 7px;
}
body > div {
width: 100%;
max-width: 620px;
margin: auto;
}
main {
border: 1px solid #e1e3e6;
background-color: #fff;
padding: 16px;
border-radius: 18px;
font-size: 15px;
}
#authHeading, #authExplainer {
color: #818c99;
padding-bottom: 12px;
}
:is(#authHeading, #authExplainer) b {
color: #000;
}
#authButtons {
display: flex;
gap: 10px;
align-items: center;
}
#authButtons a {
color: #818c99;
text-decoration: none;
}
#authButtons a:hover {
text-decoration: underline;
}
#authButtons button {
cursor: pointer;
appearance: none;
border: none;
background-color: #606060;
color: #fff;
font-weight: 600;
padding: 7px;
border-radius: 7px;
font-size: 15px;
}
</style>
</head>
<body>
<header>
<div>
<div style="width: 85px;">
</div>
<div id="ovkLogo">
<a href="/" target="_blank">O</a>
</div>
<div id="ovkUser">
<a href="/logout?hash={rawurlencode($csrfToken)}">{_header_log_out}</a>
<a id="pfpLink" href="/id0" target="_blank">
<img src="{$thisUser->getAvatarUrl('miniscule')}" />
</a>
</div>
</div>
</header>
<div>
<main>
<div id="authHeading">
{_app},
<b>
{if is_null($origin)}
{tr("identifies_itself_as", $clientName)}{else}
{tr("located_at_url", $origin)}{/if}</b>, {_wants_your_token}.
</div>
<div id="authExplainer">
<b>{_app_will_have_access_to}</b><br/>
{_oauth_scope_all|noescape}.
</div>
<div id="authButtons">
<button id="authAllow">{_oauth_grant}</button>
<a id="authDeny" href="javascript:void(0)">{_oauth_deny}</a>
</div>
</main>
</div>
{script "js/node_modules/msgpack-lite/dist/msgpack.min.js"}
{script "js/al_api.js"}
<script>
//<![CDATA[
let clientName = {$clientName};
let usePostMessage = {$usePostMessage} && window.opener != null;
let acceptsStale = {$acceptsStale};
let origin = {$origin};
let redirectUri = {$redirectUri};
document.querySelector("#authDeny").addEventListener("click", () => {
if (usePostMessage) {
window.opener.postMessage({
error: 'access_denied',
error_reason: 'user_denied',
error_description: 'User denied your request'
}, origin);
return;
}
window.location.href = redirectUri + 'error=access_denied&error_reason=user_denied&error_description=User%20denied%20your%20request';
});
document.querySelector("#authAllow").addEventListener("click", async () => {
let response = await API.Apps.getRegularToken(clientName, acceptsStale);
let ret = {
access_token: response.token,
expires_in: 0,
user_id: {$thisUser->getId()},
is_stale: response.is_stale
};
if (usePostMessage) {
window.opener.postMessage(ret, origin);
return;
}
window.location.href = redirectUri + (new URLSearchParams(ret)).toString();
});
//]]>
</script>
</body>
</html>

View file

@ -377,6 +377,8 @@ routes:
handler: "VKAPI->route"
- url: "/token"
handler: "VKAPI->tokenLogin"
- url: "/authorize"
handler: "VKAPI->OAuthLogin"
- url: "/admin/sandbox"
handler: "About->sandbox"
- url: "/admin/chandler/groups"

View file

@ -427,6 +427,22 @@ h1 {
text-transform: lowercase;
}
.action_links.disable>a,
.action_links.disable>form>input,
.action_links.disable {
cursor: not-allowed;
color: grey;
}
.action_links.loading::after {
content: "";
display: inline-block;
background-image: url('/assets/packages/static/openvk/img/loading_mini.gif');
width: 30px;
height: 7px;
margin-left: 5px;
}
.profile_link.disable>a,
.profile_link.disable {
cursor: not-allowed;
@ -587,6 +603,11 @@ input[type=radio]:hover {
background-position: 0 -28px;
}
input[type=checkbox]:disabled {
background-position: 0 -28px;
cursor: initial;
}
input[type=checkbox]:checked,
input[type=radio]:checked {
background-position: 0 -14px;
@ -597,6 +618,10 @@ input[type=radio]:checked:hover {
background-position: 0 -42px;
}
input[type=checkbox]:checked:disabled {
background-position: 0 -42px;
}
#auth {
padding: 10px;
}
@ -2059,20 +2084,17 @@ table td[width="120"] {
font-weight: bold;
margin-right: 10px;
display: inline-block;
border-radius: 2px;
}
.mb_tab div {
padding: 3px 7px;
padding: 5px 9px;
}
.mb_tab#active {
background-color: #898989;
}
.mb_tab#active div {
border: 2px solid #5f5f5f;
}
.mb_tab#active a {
color: white;
}

View file

@ -167,6 +167,23 @@ document.addEventListener("DOMContentLoaded", function() { //BEGIN
return false;
});
u("#_submitUserSubscriptionAction").handle("submit", async function(e) {
u(this).nodes[0].parentElement.classList.add('loading');
u(this).nodes[0].parentElement.classList.add('disable');
console.log(e.target);
const data = await fetch(u(this).attr('action'), { method: 'POST', body: new FormData(e.target) });
if (data.ok) {
u(this).nodes[0].parentElement.classList.remove('loading');
u(this).nodes[0].parentElement.classList.remove('disable');
if (e.target[0].value == "add") {
u(this).nodes[0].parentElement.innerHTML = tr("friends_add_msg");
} else if (e.target[0].value == "rej") {
u(this).nodes[0].parentElement.innerHTML = tr("friends_rej_msg");
} else if (e.target[0].value == "rem") {
u(this).nodes[0].parentElement.innerHTML = tr("friends_rem_msg");
}
}
})
}); //END ONREADY DECLS
async function repostPost(id, hash) {

View file

@ -200,7 +200,7 @@ function ovk_strftime_safe(string $format, ?int $timestamp = NULL): string
{
$sessionOffset = intval(Session::i()->get("_timezoneOffset"));
$str = strftime($format, $timestamp + ($sessionOffset * MINUTE) * -1 ?? time() + ($sessionOffset * MINUTE) * -1, tr("__locale") !== '@__locale' ? tr("__locale") : NULL);
if(PHP_SHLIB_SUFFIX === "dll") {
if(PHP_SHLIB_SUFFIX === "dll" && version_compare(PHP_VERSION, "8.1.0", "<")) {
$enc = tr("__WinEncoding");
if($enc === "@__WinEncoding")
$enc = "Windows-1251";
@ -232,7 +232,7 @@ function ovk_is_ssl(): bool
return $GLOBALS["requestIsSSL"];
}
function parseAttachments(string $attachments)
function parseAttachments(string $attachments): array
{
$attachmentsArr = explode(",", $attachments);
$returnArr = [];
@ -249,9 +249,10 @@ function parseAttachments(string $attachments)
elseif(str_contains($attachment, "audio"))
$attachmentType = "audio";
$attachmentIds = str_replace($attachmentType, "", $attachment);
$attachmentOwner = (int)explode("_", $attachmentIds)[0];
$attachmentId = (int)end(explode("_", $attachmentIds));
$attachmentIds = str_replace($attachmentType, "", $attachment);
$attachmentOwner = (int) explode("_", $attachmentIds)[0];
$gatoExplotano = explode("_", $attachmentIds);
$attachmentId = (int) end($gatoExplotano);
switch($attachmentType) {
case "photo":

View file

@ -2,7 +2,6 @@
"require": {
"php": "~7.3||~8.1",
"guzzlehttp/guzzle": "^6.5",
"komeiji-satori/curl": "dev-master",
"whichbrowser/parser": "dev-master",
"james-heinrich/getid3": "^1.9@dev",
"rybakit/msgpack": "dev-master",
@ -11,7 +10,7 @@
"ezyang/htmlpurifier": "dev-master",
"scssphp/scssphp": "dev-main",
"lfkeitel/phptotp": "dev-master",
"chillerlan/php-qrcode": "dev-main",
"chillerlan/php-qrcode": "5.0.2",
"vearutop/php-obscene-censor-rus": "dev-master",
"erusev/parsedown": "dev-master",
"bhaktaraz/php-rss-generator": "dev-master",
@ -20,7 +19,8 @@
"symfony/console": "5.4.x-dev",
"wapmorgan/morphos": "dev-master",
"ext-sodium": "*",
"php81_bc/strftime": "^0.0.2"
"php81_bc/strftime": "^0.0.2",
"ext-iconv": "*"
},
"minimum-stability": "dev"
"minimum-stability": "beta"
}

397
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -63,7 +63,6 @@ openvk:
caption: "Ad caption"
link: "https://example.org/product.aspx?id=10&from=ovk"
bellsAndWhistles:
fartscroll: false
testLabel: false
defaultMobileTheme: ""

View file

@ -23,7 +23,7 @@ RUN mkdir openvk
WORKDIR /opt/chandler/extensions/available/openvk
ADD . .
ADD composer.* .
RUN composer install
@ -33,10 +33,14 @@ COPY --from=builder /opt/chandler /opt/chandler
WORKDIR /opt/chandler/extensions/available/openvk/Web/static/js
ADD Web/static/js/package.json Web/static/js/package-lock.json Web/static/js/yarn.lock ./
RUN yarn install
WORKDIR /opt/chandler/extensions/available/openvk
ADD . .
ARG GITREPO=openvk/openvk
FROM ghcr.io/${GITREPO}/php:8.2-apache

View file

@ -101,7 +101,6 @@ openvk:
caption: "Ad caption"
link: "https://example.org/product.aspx?id=10&from=ovk"
bellsAndWhistles:
fartscroll: false
testLabel: false
defaultMobileTheme: ""
defaultFeaturePhoneTheme: ""

View file

@ -97,7 +97,6 @@ data:
caption: "Ad caption"
link: "https://example.org/product.aspx?id=10&from=ovk"
bellsAndWhistles:
fartscroll: false
testLabel: false
defaultMobileTheme: ""

View file

@ -0,0 +1 @@
ALTER TABLE `groups` ADD COLUMN `enforce_hiding_from_global_feed` boolean NOT NULL DEFAULT 0 AFTER `hide_from_global_feed`;

View file

@ -0,0 +1 @@
ALTER TABLE `subscriptions` ADD `flags` tinyint(3) unsigned NOT NULL DEFAULT '0' AFTER `target`

View file

@ -131,6 +131,7 @@
"friends_delete" = "Выдаліць з сяброў";
"friends_reject" = "Адмяніць заяўку";
"friends_accept" = "Прыняць заяўку";
"friends_leave_in_flw" = "Пакінуть у падпісчыках";
"send_message" = "Адправіць паведамленне";
"incoming_req" = "Падпісанты";
"outcoming_req" = "Заяўкі";

View file

@ -184,10 +184,10 @@
"post_writes_g" = "published";
"post_deact_m" = "deleted his profile saying:";
"post_deact_f" = "deleted her profile saying:";
"post_deact_g" = "deleted they profile saying:";
"post_deact_g" = "deleted their profile saying:";
"post_deact_silent_m" = "silently deleted his profile.";
"post_deact_silent_f" = "silently deleted her profile.";
"post_deact_silent_f" = "silently deleted they profile.";
"post_deact_silent_f" = "silently deleted their profile.";
"post_on_your_wall" = "on your wall";
"post_on_group_wall" = "in $1";
"post_on_user_wall" = "on $1's wall";
@ -259,6 +259,10 @@
"friends_delete" = "Remove from friends";
"friends_reject" = "Reject request";
"friends_accept" = "Accept request";
"friends_leave_in_flw" = "Leave in followers";
"friends_add_msg" = "Now you're friends.";
"friends_rej_msg" = "You left this user as subscriber.";
"friends_rem_msg" = "You deleted this user from your friend list.";
"send_message" = "Send a message";
"incoming_req" = "Pending";
"outcoming_req" = "Outgoing";
@ -481,6 +485,7 @@
"upd_m" = "updated his profile picture";
"upd_f" = "updated her profile picture";
"upd_n" = "updated their profile picture";
"upd_g" = "updated group's picture";
"add_photos" = "Add photos";
@ -777,6 +782,15 @@
"disable_2fa" = "Turn off 2FA";
"viewing" = "View";
/* OAuth */
"identifies_itself_as" = "that identifies itself as $1";
"located_at_url" = "located at $1";
"wants_your_token" = "wants to access your account";
"app_will_have_access_to" = "App will have access to:";
"oauth_scope_all" = "profile information, status, list of friends, photos, wall posts, audios, videos, notifications, fishing rod handle, messages, gifts, <b>your e-mail</b>, polls, communities, discussions, notes, <b>payment method</b>, likes and comments";
"oauth_grant" = "Allow";
"oauth_deny" = "Deny";
/* Sorting */
"sort_randomly" = "Sort randomly";
@ -832,7 +846,7 @@
"limits" = "Limits";
"select_audio" = "Select audio from your computer";
"audio_requirements" = "Audio must be between $1s to $2 minutes, weights to $3MB and contain audio stream.";
"audio_requirements" = "Audio must be between $1 seconds to $2 minutes, weights to $3 MB and contain audio stream.";
"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";
"search_audio_inst" = "audios search";
@ -840,7 +854,7 @@
"audio_embed_not_found" = "Audio not found";
"audio_embed_deleted" = "Audio was deleted";
"audio_embed_withdrawn" = "The audio was withdrawn at the request of the copyright holder";
"audio_embed_forbidden" = "The user's privacy settings do not allow this embed this audio";
"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.";
"audios_count_zero" = "No audios";
@ -1190,6 +1204,7 @@
"report_number" = "Report #";
"list_of_reports" = "List of reports";
"text_of_the_post" = "Text of the post";
"delete_content" = "Delete content";
"today" = "today";
"will_be_watched" = "It will be reviewed by the moderators soon";
@ -1582,6 +1597,7 @@
"admin_user_online_deceased" = "Deceased";
"admin_club_search" = "Search for groups";
"admin_club_excludeglobalfeed" = "Do not display posts in the global feed";
"admin_club_enforceexcludeglobalfeed" = "Disallow group staff from changing global feed status";
"admin_services" = "Paid services";
"admin_newgift" = "New gift";
@ -1617,6 +1633,9 @@
"admin_commerce_disabled" = "Commerce has been disabled by the system administrator";
"admin_commerce_disabled_desc" = "The voucher and gift settings will be saved, but will have no effect.";
"admin_longpool_broken" = "Longpool is broken and will not work!";
"admin_longpool_broken_desc" = "Make sure file at the path <code>$1</code> exist and have correct rights and ownership.";
"admin_banned_links" = "Blocked links";
"admin_banned_link" = "Link";
"admin_banned_domain" = "Domain";
@ -1700,7 +1719,7 @@
"about_wall_posts_one" = "<b>1</b> wall post";
"about_wall_posts_other" = "<b>$1</b> wall posts";
"about_watch_rules" = "Watch <a href='$1'>here</a>.";
"about_watch_rules" = "See <a href='$1'>here</a>.";
/* Dialogs */
@ -1910,9 +1929,9 @@
"tour_section_11_title_1" = "Themes";
"tour_section_11_text_1" = "Upon registration, the default theme will be set as your appearance.";
"tour_section_11_text_2" = "Some new users might find the current default theme a bit dated.";
"tour_section_11_text_3" = "<b>No worries:</b> You can create your own theme by reading the <a href='https://docs.openvk.uk/'>documentation</a> or choose one from the catalog.";
"tour_section_11_text_3" = "<b>No worries:</b> You can create your own theme by reading the <a href='https://docs.ovk.to/'>documentation</a> or choose one from the catalog.";
"tour_section_11_bottom_text_1" = "A catalog of themes is available under \"My Settings\" in the \"Interface\" tab.";
"tour_section_11_wordart" = "<img src='https://openvk.uk/assets/packages/static/openvk/img/tour/wordart_en.png' width='65%'>";
"tour_section_11_wordart" = "<img src='/assets/packages/static/openvk/img/tour/wordart_en.png' width='65%'>";
"tour_section_12_title_1" = "Profile and Group Backgrounds";
"tour_section_12_text_1" = "You can set two images as the background of your page.";

View file

@ -1447,9 +1447,9 @@
"tour_section_11_title_1" = "Տեսքեր";
"tour_section_11_text_1" = "Գրանցվելուց հետո Ձեր էջում կիրառվում է սովորական տեսքը";
"tour_section_11_text_2" = "Որոշ նորեկները կարող է չսիրեն լռելյայն տեսքը, քանի որ այն անգամ հնության զգացում է տալիս";
"tour_section_11_text_3" = "<b>Բայց հլը հո՛պ.</b> Դուք կարող եք անգամ ստեղծել Ձեր տեսքը ՝ կարդալով <a href='https://docs.openvk.uk/'>դոկումենտացիան</a>, կամ էլ ընտրել եղածներից մեկը";
"tour_section_11_text_3" = "<b>Բայց հլը հո՛պ.</b> Դուք կարող եք անգամ ստեղծել Ձեր տեսքը ՝ կարդալով <a href='https://docs.ovk.to/'>դոկումենտացիան</a>, կամ էլ ընտրել եղածներից մեկը";
"tour_section_11_bottom_text_1" = "Տեսքերի ցանկը հասանելի է &quot;Իմ Կարգավորումներ&quot; –ի &quot;Ինտերֆեյս&quot; բաժնում;";
"tour_section_11_wordart" = "<img src='https://openvk.uk/assets/packages/static/openvk/img/tour/wordart_en.png' width='65%'>";
"tour_section_11_wordart" = "<img src='/assets/packages/static/openvk/img/tour/wordart_en.png' width='65%'>";
"tour_section_12_title_1" = "Պրոֆիլ և խմբի ետնապատկերներ";
"tour_section_12_text_1" = "Դուք կարող եք երկու ետնապատկեր տեղադրել";

View file

@ -239,6 +239,10 @@
"friends_delete" = "Удалить из друзей";
"friends_reject" = "Отменить заявку";
"friends_accept" = "Принять заявку";
"friends_leave_in_flw" = "Оставить в подписчиках";
"friends_add_msg" = "Теперь вы друзья.";
"friends_rej_msg" = "Вы оставили пользователя в подписчиках.";
"friends_rem_msg" = "Вы удалили пользователя из списка своих друзей.";
"send_message" = "Отправить сообщение";
"incoming_req" = "Входящие";
"outcoming_req" = "Исходящие";
@ -739,6 +743,15 @@
"disable_2fa" = "Отключить 2FA";
"viewing" = "Просмотреть";
/* OAuth */
"identifies_itself_as" = "идентифицирующее себя как $1";
"located_at_url" = "располагающееся по адресу $1";
"wants_your_token" = "запрашивает доступ к вашему аккаунту";
"app_will_have_access_to" = "Приложению будут доступны:";
"oauth_scope_all" = "информация страницы, обновление статуса, список друзей, фотографии, публикация записей, аудиозаписи, видео, уведомления, сообщения, подарки, <b>ваш адрес электронной почты</b>, опросы, группы, обсуждения, заметки, <b>голоса</b>, лайки и комментарии";
"oauth_grant" = "Разрешить";
"oauth_deny" = "Отмена";
/* Sorting */
"sort_randomly" = "Сортировать случайно";
@ -1123,6 +1136,7 @@
"report_number" = "Жалоба №";
"list_of_reports" = "Список жалоб";
"text_of_the_post" = "Текст записи";
"delete_content" = "Удалить контент";
"today" = "сегодня";
"will_be_watched" = "Скоро её рассмотрят модераторы";
@ -1479,6 +1493,7 @@
"admin_user_online_deceased" = "Покойник";
"admin_club_search" = "Поиск групп";
"admin_club_excludeglobalfeed" = "Не отображать записи в глобальной ленте";
"admin_club_enforceexcludeglobalfeed" = "Запретить руководству группы изменять отображение в глобальной ленте";
"admin_services" = "Платные услуги";
"admin_newgift" = "Новый подарок";
"admin_price" = "Цена";
@ -1509,6 +1524,8 @@
"admin_about_instance" = "Инстанция";
"admin_commerce_disabled" = "Коммерция отключена системным администратором";
"admin_commerce_disabled_desc" = "Настройки ваучеров и подарков будут сохранены, но не будут оказывать никакого влияния.";
"admin_longpool_broken" = "Longpool сломан!";
"admin_longpool_broken_desc" = "Проверьте, существует ли файл по пути <code>$1</code> и выданы ли у него правильные права на запись.";
"admin_banned_links" = "Заблокированные ссылки";
"admin_banned_link" = "Ссылка";
"admin_banned_domain" = "Домен";
@ -1802,9 +1819,9 @@
"tour_section_11_title_1" = "Темы оформления";
"tour_section_11_text_1" = "После регистрации, в качестве оформления у вас будет установлена стандартная тема";
"tour_section_11_text_2" = "Некоторых новых пользователей может слегка отпугнуть нынешняя стоковая тема, которая веет совсем уж древностью";
"tour_section_11_text_3" = "<b>Но не беда:</b> Вы можете создать свою тему для сайта, ознакомившись с <a href='https://docs.openvk.uk/'>документацией</a> или выбрать уже существующую из каталога";
"tour_section_11_text_3" = "<b>Но не беда:</b> Вы можете создать свою тему для сайта, ознакомившись с <a href='https://docs.ovk.to/'>документацией</a> или выбрать уже существующую из каталога";
"tour_section_11_bottom_text_1" = "Каталог тем доступен в разделе &quot;Мои Настройки&quot; во вкладке &quot;Интерфейс&quot; ";
"tour_section_11_wordart" = "<img src='https://openvk.uk/assets/packages/static/openvk/img/tour/wordart.png' width='65%'>";
"tour_section_11_wordart" = "<img src='/assets/packages/static/openvk/img/tour/wordart.png' width='65%'>";
"tour_section_12_title_1" = "Фон профиля и группы";
"tour_section_12_text_1" = "Вы можете установить два изображения в качестве фона вашей страницы";

View file

@ -1669,9 +1669,9 @@
"tour_section_11_title_1" = "Temy oformlenija";
"tour_section_11_text_1" = "Posle registracii, v kačestve oformlenija u vas budet ustanovlena standartnaja tema";
"tour_section_11_text_2" = "Nekotoryh novyh polízovatelej možet slegka otpugnutí nynešnjaja stokovaja tema, kotoraja veet sovsem už drevnostíju";
"tour_section_11_text_3" = "<b>No ne beda:</b> Vy možete sozdatí svoju temu dlja sajta, oznakomivšisí s <a href='https://docs.openvk.uk/'>dokumentaciej</a> ili vybratí uže susčestvujusčuju iz kataloga";
"tour_section_11_text_3" = "<b>No ne beda:</b> Vy možete sozdatí svoju temu dlja sajta, oznakomivšisí s <a href='https://docs.ovk.to/'>dokumentaciej</a> ili vybratí uže susčestvujusčuju iz kataloga";
"tour_section_11_bottom_text_1" = "Katalog tem dostupen v razdele &quot;Moi Nastrojki&quot; vo vkladke &quot;Interfejs&quot; ";
"tour_section_11_wordart" = "<img src='https://openvk.uk/assets/packages/static/openvk/img/tour/wordart.png' width='65%'>";
"tour_section_11_wordart" = "<img src='/assets/packages/static/openvk/img/tour/wordart.png' width='65%'>";
"tour_section_12_title_1" = "Fon profilja i gruppy";
"tour_section_12_text_1" = "Vy možete ustanovití dva izobraženija v kačestve fona vašej stranicy";

View file

@ -213,6 +213,7 @@
"friends_delete" = "Видалити з друзів";
"friends_reject" = "Скасувати заявку";
"friends_accept" = "Прийняти заявку";
"friends_leave_in_flw" = "Залишити у підписниках";
"send_message" = "Відправити повідомлення";
"incoming_req" = "Підписники";
"outcoming_req" = "Вихідні";
@ -1706,9 +1707,9 @@
"tour_section_11_title_1" = "Теми оформлення";
"tour_section_11_text_1" = "Після реєстрації, як стандартна тема, у вас буде класична тема оформлення";
"tour_section_11_text_2" = "Деяких нових користувачів може налякати чинна класична тема, яка виглядає дуже архаїчно";
"tour_section_11_text_3" = "<b>Але не біда:</b> Ви можете обрати іншу тему з каталогу, або створити свою, ознаомившись з <a href='https://docs.openvk.uk/'>документацією</a>";
"tour_section_11_text_3" = "<b>Але не біда:</b> Ви можете обрати іншу тему з каталогу, або створити свою, ознаомившись з <a href='https://docs.ovk.to/'>документацією</a>";
"tour_section_11_bottom_text_1" = "Каталог тем доступний в розділі &quot;Мої Налаштування&quot; в вкладці &quot;Інтерфейс&quot; ";
"tour_section_11_wordart" = "<img src='https://openvk.uk/assets/packages/static/openvk/img/tour/wordart.png' width='65%'>";
"tour_section_11_wordart" = "<img src='/assets/packages/static/openvk/img/tour/wordart.png' width='65%'>";
"tour_section_12_title_1" = "Фон профілю та групи";
"tour_section_12_text_1" = "Ви можете встановити одну чи два зображення як фон вашої сторінки";

View file

@ -101,7 +101,6 @@ openvk:
caption: "Ad caption"
link: "https://example.org/product.aspx?id=10&from=ovk"
bellsAndWhistles:
fartscroll: false
testLabel: false
defaultMobileTheme: ""
defaultFeaturePhoneTheme: ""

View file

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

View file

@ -6,7 +6,10 @@ html {
color-scheme: dark !important;
}
body, #backdropDripper, #standaloneCommentBox {
body,
#backdropDripper,
#standaloneCommentBox,
.ovk-photo-view {
background-color: #0e0b1a;
color: #c6d2e8;
}
@ -15,11 +18,17 @@ body, #backdropDripper, #standaloneCommentBox {
box-shadow: -30px 0px 20px 20px #0e0b1a, -50px 0px 20px 20px hsl(252 41% 7% / 59%), -70px 0px 20px 20px hsl(252 41% 7% / 43%), -90px 0px 20px 20px hsl(252 41% 7% / 35%), -110px 0px 20px 20px hsl(252 41% 7% / 28%), -130px 0px 20px 20px hsl(252 41% 7% / 16%), 30px 0px 20px 20px #0e0b1a, 50px 0px 20px 20px hsl(252 41% 7% / 59%), 70px 0px 20px 20px hsl(252 41% 7% / 43%), 90px 0px 20px 20px hsl(252 41% 7% / 35%), 110px 0px 20px 20px hsl(252 41% 7% / 28%), 130px 0px 20px 20px hsl(252 41% 7% / 16%);
}
span, .post-author .date, .crp-entry--message---text, .messenger-app--messages---message .time, .navigation-lang .link_new, .tippy-box text {
span,
.post-author .date,
.crp-entry--message---text,
.messenger-app--messages---message .time,
.navigation-lang .link_new,
.tippy-box text {
color: #8b9ab5 !important;
}
.nobold, nobold {
.nobold,
nobold {
color: #6f82a8;
}
@ -31,15 +40,103 @@ span, .post-author .date, .crp-entry--message---text, .messenger-app--messages--
color: #8eb2d0;
}
.wrap1, .wrap2, .page-wrap, #wrapH, #wrapHI {
.wrap1,
.wrap2,
.page-wrap,
#wrapH,
#wrapHI {
border-color: #1c202f;
}
.accountInfo, .left_small_block, #profile_link, .profile_link, .navigation .link, .navigation .link:hover, .navigation_footer .link, .navigation_footer .link:hover, .completeness-gauge, input[type="text"], input[type="password"], input[type~="text"], input[type~="password"], input[type="email"], input[type="phone"], input[type~="email"], input[type~="phone"], input[type="search"], input[type~="search"], input[type~="date"], select, .content_title_expanded, .content_title_unexpanded, .content_subtitle, textarea, .post-content, .post-author, hr, h4, .postFeedWrapper, .tabs, #wallAttachmentMenu, .ovk-diag, .ovk-diag-head, #ovkDraw, #ovkDraw .literally .lc-picker, .literally .lc-options.horz-toolbar, .page_wrap, .container_gray .content, .summaryBar, .groups_options, form[action="/search"] > input, .header_search_input, .header_search_inputbt, .accent-box, .page_status_popup, .messenger-app--input, .messenger-app, .crp-entry:first-of-type, .crp-list, .crp-entry, .note_footer, .page_content > div, #editor, .note_header, center[style="background: white;border: #DEDEDE solid 1px;"], .album-photo img, .mb_tabs, .mb_tab#active div, .navigation-lang .link_new, #faqhead, #faqcontent, .post-divider, .comment, .commentsTextFieldWrap, tr, td, th, #votesBalance, .paginator a.active, .paginator a:hover, .topic-list-item, #userContent blockquote, .tippy-box[data-theme~="vk"], .poll, #standaloneCommentBox, .searchBtn, .searchList #used, .searchOptionName, .borderup, #tour, #auth, .ovk-photo-view, .searchOptions {
.accountInfo,
.left_small_block,
#profile_link,
.profile_link,
.navigation .link,
.navigation .link:hover,
.navigation_footer .link,
.navigation_footer .link:hover,
.completeness-gauge,
input[type="text"],
input[type="password"],
input[type~="text"],
input[type~="password"],
input[type="email"],
input[type="phone"],
input[type~="email"],
input[type~="phone"],
input[type="search"],
input[type~="search"],
input[type~="date"],
select,
.content_title_expanded,
.content_title_unexpanded,
.content_subtitle,
textarea,
.post-content,
.post-author,
hr,
h4,
.postFeedWrapper,
.tabs,
#wallAttachmentMenu,
.ovk-diag,
.ovk-diag-head,
#ovkDraw,
#ovkDraw .literally .lc-picker,
.literally .lc-options.horz-toolbar,
.page_wrap,
.container_gray .content,
.summaryBar,
.groups_options,
form[action="/search"]>input,
.header_search_input,
.header_search_inputbt,
.accent-box,
.page_status_popup,
.messenger-app--input,
.messenger-app,
.crp-entry:first-of-type,
.crp-list,
.crp-entry,
.note_footer,
.page_content>div,
#editor,
.note_header,
center[style="background: white;border: #DEDEDE solid 1px;"],
.album-photo img,
.mb_tabs,
.mb_tab#active div,
.navigation-lang .link_new,
#faqhead,
#faqcontent,
.post-divider,
.comment,
.commentsTextFieldWrap,
tr,
td,
th,
#votesBalance,
.paginator a.active,
.paginator a:hover,
.topic-list-item,
#userContent blockquote,
.tippy-box[data-theme~="vk"],
.poll,
#standaloneCommentBox,
.searchBtn,
.searchList #used,
.searchOptionName,
.borderup,
#tour,
#auth,
.ovk-photo-view,
.searchOptions {
border-color: #2c2640 !important;
}
.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^='top']>.tippy-arrow::before,
.tippy-box[data-theme~="vk"][data-placement^='bottom']>.tippy-arrow::before {
border-top-color: #1e1a2b;
border-bottom-color: #1e1a2b;
}
@ -53,7 +150,13 @@ hr {
box-shadow: unset;
}
.button, #activetabs, .messagebox-content-header, .accent-box, .button_search, .searchBtn, .searchOptionName {
.button,
#activetabs,
.messagebox-content-header,
.accent-box,
.button_search,
.searchBtn,
.searchOptionName {
background-color: #383052;
}
@ -61,7 +164,9 @@ hr {
background-color: #40375e;
}
.menu_divider, .ovk-diag-action, .minilink .counter {
.menu_divider,
.ovk-diag-action,
.minilink .counter {
background-color: #2c2640;
}
@ -70,11 +175,14 @@ hr {
border-color: #2c2640;
}
.bsdn_contextMenuElement:hover, .searchList li:hover {
.bsdn_contextMenuElement:hover,
.searchList li:hover {
background-color: #29223a;
}
#ovkDraw .literally .lc-picker, .literally .lc-options.horz-toolbar, .mb_tab#active {
#ovkDraw .literally .lc-picker,
.literally .lc-options.horz-toolbar,
.mb_tab#active {
background-color: #453e5e !important;
}
@ -82,19 +190,35 @@ hr {
background-color: #272e4894;
}
a, .page_footer .link, #profile_link, .profile_link {
a,
.page_footer .link,
#profile_link,
.profile_link {
color: #8fb9d8;
}
.page_footer .link:hover, .navigation .link:hover, .navigation .edit-button:hover, #profile_link:hover, .profile_link:hover, #wallAttachmentMenu > a:hover, .crp-entry:hover, .navigation-lang .link_new:hover, .paginator a:hover, .post-share-button:hover, .post-like-button:hover, .searchBtn:active {
.page_footer .link:hover,
.navigation .link:hover,
.navigation .edit-button:hover,
#profile_link:hover,
.profile_link:hover,
#wallAttachmentMenu>a:hover,
.crp-entry:hover,
.navigation-lang .link_new:hover,
.paginator a:hover,
.post-share-button:hover,
.post-like-button:hover,
.searchBtn:active {
background-color: #272138 !important;
}
.header_navigation .link a, .searchOptionName {
.header_navigation .link a,
.searchOptionName {
color: #bcc3d0;
}
.header_navigation .link a:hover, .home_button_custom {
.header_navigation .link a:hover,
.home_button_custom {
color: #c7cdd9;
}
@ -107,7 +231,8 @@ a, .page_footer .link, #profile_link, .profile_link {
color: #7b94c4 !important;
}
#test-label, .msg.msg_err {
#test-label,
.msg.msg_err {
background-color: #30161d;
}
@ -115,19 +240,47 @@ a, .page_footer .link, #profile_link, .profile_link {
background-color: #163f13;
}
h4, .content_title_expanded, .summaryBar .summary, .content_title_unexpanded {
h4,
.content_title_expanded,
.summaryBar .summary,
.content_title_unexpanded {
color: #7c94c5;
}
.notes_titles small, .post-upload, .post-has-poll {
.notes_titles small,
.post-upload,
.post-has-poll {
color: #6f82a8;
}
.content_title_expanded, .content_title_unexpanded, .ovk-diag, .settings_delete, center[style="background: white;border: #DEDEDE solid 1px;"], .album-photo img, #faqhead, td.e, tr.e {
.content_title_expanded,
.content_title_unexpanded,
.ovk-diag,
.settings_delete,
center[style="background: white;border: #DEDEDE solid 1px;"],
.album-photo img,
#faqhead,
td.e,
tr.e {
background-color: #231e33 !important;
}
.content_subtitle, .postFeedWrapper, .ovk-diag-head, .container_gray, .page_status_popup, .messenger-app--input, .note_header, #faqcontent, .commentsTextFieldWrap, td.v, tr.v, #votesBalance, .expand_button, #userContent blockquote, .tippy-box[data-theme~="vk"], .searchOptions {
.content_subtitle,
.postFeedWrapper,
.ovk-diag-head,
.container_gray,
.page_status_popup,
.messenger-app--input,
.note_header,
#faqcontent,
.commentsTextFieldWrap,
td.v,
tr.v,
#votesBalance,
.expand_button,
#userContent blockquote,
.tippy-box[data-theme~="vk"],
.searchOptions {
background-color: #1e1a2b !important;
}
@ -137,22 +290,27 @@ h4, .content_title_expanded, .summaryBar .summary, .content_title_unexpanded {
}
.content_title_expanded {
background-image: url("/themepack/midnight/0.0.2.8/resource/flex_arrow_open.png") !important;
background-image: url("/themepack/midnight/0.0.2.9/resource/flex_arrow_open.png") !important;
}
.content_title_unexpanded {
background-image: url("/themepack/midnight/0.0.2.8/resource/flex_arrow_shut.gif") !important;
background-image: url("/themepack/midnight/0.0.2.9/resource/flex_arrow_shut.gif") !important;
}
.ovk-video > .preview, .video-preview {
.ovk-video>.preview,
.video-preview {
box-shadow: inset 0 0 0 1px #231e33, inset 0 0 0 2px #1e1a2b;
}
#wallAttachmentMenu, .container_gray .content, .mb_tabs {
#wallAttachmentMenu,
.container_gray .content,
.mb_tabs {
background-color: #120e1f;
}
#wallAttachmentMenu > .header, .messenger-app--messages---message.unread, tr.h {
#wallAttachmentMenu>.header,
.messenger-app--messages---message.unread,
tr.h {
background-color: #1d192b;
}
@ -163,41 +321,59 @@ h4, .content_title_expanded, .summaryBar .summary, .content_title_unexpanded {
.page_yellowheader {
color: #c6d2e8;
background-image: url("/themepack/midnight/0.0.2.8/resource/header_purple.png") !important;
background-image: url("/themepack/midnight/0.0.2.9/resource/header_purple.png") !important;
background-color: #231f34;
border-color: #231f34;
}
.page_header {
background-image: url("/themepack/midnight/0.0.2.8/resource/header.png") !important;
background-image: url("/themepack/midnight/0.0.2.9/resource/header.png") !important;
}
.page_custom_header {
background-image: url("/themepack/midnight/0.0.2.8/resource/header_custom.png") !important;
background-image: url("/themepack/midnight/0.0.2.9/resource/header_custom.png") !important;
}
.page_yellowheader span, .page_yellowheader a {
.page_yellowheader span,
.page_yellowheader a {
color: #a48aff !important;
}
.completeness-gauge, .poll-result-bar {
.completeness-gauge,
.poll-result-bar {
background-color: #231e33;
}
.completeness-gauge > div, .poll-result-bar-sub {
.completeness-gauge>div,
.poll-result-bar-sub {
background-color: #2c2640;
}
form[action="/search"] > input, .header_search_input, textarea, input[type="text"], input[type="password"], input[type~="text"], input[type~="password"], input[type="email"], input[type="phone"], input[type~="email"], input[type~="phone"], input[type="search"], input[type~="search"], input[type~="date"], select, .crp-entry--message.unread {
form[action="/search"]>input,
.header_search_input,
textarea,
input[type="text"],
input[type="password"],
input[type~="text"],
input[type~="password"],
input[type="email"],
input[type="phone"],
input[type~="email"],
input[type~="phone"],
input[type="search"],
input[type~="search"],
input[type~="date"],
select,
.crp-entry--message.unread {
background-color: #181826 !important;
}
input[type="checkbox"] {
background-image: url("/themepack/midnight/0.0.2.8/resource/checkbox.png") !important;
background-image: url("/themepack/midnight/0.0.2.9/resource/checkbox.png") !important;
}
input[type="radio"] {
background-image: url("/themepack/midnight/0.0.2.8/resource/radio.png") !important;
background-image: url("/themepack/midnight/0.0.2.9/resource/radio.png") !important;
}
.header_navigation .link {
@ -205,19 +381,20 @@ input[type="radio"] {
}
.heart {
background-image: url("/themepack/midnight/0.0.2.8/resource/like.gif") !important;
background-image: url("/themepack/midnight/0.0.2.9/resource/like.gif") !important;
}
.pinned-mark, .post-author .pin {
background-image: url("/themepack/midnight/0.0.2.8/resource/pin.png") !important;
.pinned-mark,
.post-author .pin {
background-image: url("/themepack/midnight/0.0.2.9/resource/pin.png") !important;
}
.repost-icon {
background-image: url("/themepack/midnight/0.0.2.8/resource/published.gif") !important;
background-image: url("/themepack/midnight/0.0.2.9/resource/published.gif") !important;
}
.post-author .delete {
background-image: url("/themepack/midnight/0.0.2.8/resource/input_clear.gif") !important;
background-image: url("/themepack/midnight/0.0.2.9/resource/input_clear.gif") !important;
}
.user-alert {
@ -239,7 +416,7 @@ input[type="radio"] {
}
#backdropEditor {
background-image: url("/themepack/midnight/0.0.2.8/resource/backdrop-editor.gif") !important;
background-image: url("/themepack/midnight/0.0.2.9/resource/backdrop-editor.gif") !important;
border-color: #473e66 !important;
}
@ -260,11 +437,13 @@ input[type="radio"] {
background-color: rgb(30, 26, 43) !important;
}
.bigPlayer .selectableTrack, .audioEmbed .track > .selectableTrack {
.bigPlayer .selectableTrack,
.audioEmbed .track>.selectableTrack {
border-top: #b9b9b9 1px solid !important;
}
.bigPlayer .paddingLayer .slider, .audioEmbed .track .slider {
.bigPlayer .paddingLayer .slider,
.audioEmbed .track .slider {
background: #b9b9b9 !important;
}
@ -323,7 +502,8 @@ input[type="radio"] {
filter: invert(81%);
}
img[src$='/assets/packages/static/openvk/img/camera_200.png'], img[src$='/assets/packages/static/openvk/img/song.jpg'] {
img[src$='/assets/packages/static/openvk/img/camera_200.png'],
img[src$='/assets/packages/static/openvk/img/song.jpg'] {
filter: invert(100%);
}
@ -339,7 +519,8 @@ img[src$='/assets/packages/static/openvk/img/camera_200.png'], img[src$='/assets
color: unset !important;
}
#upload_container, .whiteBox {
#upload_container,
.whiteBox {
background: #1d1928 !important;
border: 1px solid #383052 !important;
}
@ -375,15 +556,17 @@ ul {
cursor: pointer;
}
.showMore, .showMoreAudiosPlaylist {
.showMore,
.showMoreAudiosPlaylist {
background: #181826 !important;
}
/* Tour */
.rightNav h1{
.rightNav h1 {
background: #000;
}
.tabcontent{
.tabcontent {
background: #2c2640 !important;
}

View file

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