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 id: buildx
uses: docker/setup-buildx-action@v2 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 - name: Log into registry
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
- name: Build cli image - name: Build cli image
run: | 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 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 id: buildx
uses: docker/setup-buildx-action@v2 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 - name: Log into registry
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
- name: Build apache image - name: Build apache image
run: | 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 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 id: buildx
uses: docker/setup-buildx-action@v2 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 - name: Log into registry
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
- name: Build base image - name: Build base image
run: | 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]') IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')
VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,') VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')
[[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//') [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')
@ -49,16 +55,16 @@ jobs:
echo IMAGE_ID=$IMAGE_ID echo IMAGE_ID=$IMAGE_ID
echo VERSION=$VERSION 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 - name: Build MariaDB primary image
run: | 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 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 - name: Build MariaDB event image
run: | 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 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> <tr>
<td class="float-center" align="center" valign="top"> <td class="float-center" align="center" valign="top">
<center> <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> </center>
</td> </td>
</tr> </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)_ _[Русский](README_RU.md)_
@ -6,7 +6,7 @@ _[Русский](README_RU.md)_
VKontakte belongs to Pavel Durov and VK Group. 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? ## 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. 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 ### Installation procedure
1. Install PHP 7.4, web-server, Composer, Node.js, Yarn and [Chandler](https://github.com/openvk/chandler) 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` * **Password**: `admin`
* It is recommended to change the password of the built-in account or disable it. * 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? ### Looking for Docker or Kubernetes deployment?
See `install/automated/docker/README.md` and `install/automated/kubernetes/README.md` for Docker and Kubernetes deployment instructions. 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: You may reach out to us via:
* [Bug Tracker](https://github.com/openvk/openvk/projects/1) * [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. * Telegram Chat: Go to [our channel](https://t.me/openvkenglish) and open discussion in our channel menu.
* [Reddit](https://www.reddit.com/r/openvk/) * [Reddit](https://www.reddit.com/r/openvk/)
* [GitHub Discussions](https://github.com/openvk/openvk/discussions) * [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)_ _[English](README.md)_
@ -6,7 +6,7 @@ _[English](README.md)_
ВКонтакте принадлежит Павлу Дурову и VK Group. ВКонтакте принадлежит Павлу Дурову и 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` * **Пароль**: `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 # Установка в Docker/Kubernetes
Подробные иструкции можно найти в `install/automated/docker/README.md` и `install/automated/kubernetes/README.md` соответственно. Подробные иструкции можно найти в `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) * [Баг-трекер](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) и откройте обсуждение в меню нашего канала. * Telegram-чат: Перейдите на [наш канал](https://t.me/openvk) и откройте обсуждение в меню нашего канала.
* [Reddit](https://www.reddit.com/r/openvk/) * [Reddit](https://www.reddit.com/r/openvk/)
* [GitHub Discussions](https://github.com/openvk/openvk/discussions) * [GitHub Discussions](https://github.com/openvk/openvk/discussions)

View file

@ -1,8 +1,11 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
namespace openvk\ServiceAPI; namespace openvk\ServiceAPI;
use openvk\Web\Models\Entities\APIToken;
use openvk\Web\Models\Entities\User; use openvk\Web\Models\Entities\User;
use openvk\Web\Models\Repositories\APITokens;
use openvk\Web\Models\Repositories\Applications; use openvk\Web\Models\Repositories\Applications;
use WhichBrowser;
class Apps implements Handler class Apps implements Handler
{ {
@ -89,4 +92,25 @@ class Apps implements Handler
$app->withdrawCoins(); $app->withdrawCoins();
$resolve($coins); $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; 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) if ($count >= 1000)
$this->fail(100, "One of the required parameters was not passed or is invalid."); $this->fail(100, "One of the required parameters was not passed or is invalid.");
@ -158,10 +158,19 @@ final class Friends extends VKAPIRequestHandler
$offset++; $offset++;
$followers = []; $followers = [];
if ($out != 0) {
foreach($this->getUser()->getFollowers($offset, $count) as $follower) { foreach($this->getUser()->getFollowers($offset, $count) as $follower) {
$followers[$i] = $follower->getId(); $followers[$i] = $follower->getId();
$i++; $i++;
} }
}
else
{
foreach($this->getUser()->getRequests($offset, $count) as $follower) {
$followers[$i] = $follower->getId();
$i++;
}
}
$response = $followers; $response = $followers;
$usersApi = new Users($this->getUser()); $usersApi = new Users($this->getUser());

View file

@ -347,7 +347,10 @@ final class Groups extends VKAPIRequestHandler
!empty($topics) ? $club->setEveryone_Can_Create_Topics($topics) : NULL; !empty($topics) ? $club->setEveryone_Can_Create_Topics($topics) : NULL;
!empty($adminlist) ? $club->setAdministrators_List_Display($adminlist) : NULL; !empty($adminlist) ? $club->setAdministrators_List_Display($adminlist) : NULL;
!empty($topicsAboveWall) ? $club->setDisplay_Topics_Above_Wall($topicsAboveWall) : NULL; !empty($topicsAboveWall) ? $club->setDisplay_Topics_Above_Wall($topicsAboveWall) : NULL;
if (!$club->isHidingFromGlobalFeedEnforced()) {
!empty($hideFromGlobalFeed) ? $club->setHide_From_Global_Feed($hideFromGlobalFeed) : NULL; !empty($hideFromGlobalFeed) ? $club->setHide_From_Global_Feed($hideFromGlobalFeed) : NULL;
}
in_array($audio, [0, 1]) ? $club->setEveryone_can_upload_audios($audio) : 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) "notes_count" => (new Notes)->getUserNotesCount($usr)
]; ];
break; 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")), "object_id" => (int) substr($screen_name, strlen("club")),
"type" => "group" "type" => "group"
]; ];
} } else $this->fail(104, "Not found");
} else { } else {
$user = (new Users)->getByShortURL($screen_name); $user = (new Users)->getByShortURL($screen_name);
if($user) { 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 **Note**: requests to API are routed through
openvk.Web.Presenters.VKAPIPresenter, this dir contains only handlers. 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 ## Implementing API methods

View file

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

View file

@ -114,7 +114,7 @@ class Photo extends Media
return true; 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"])) if(isset($this->changes["hash"]))
$hash = $this->changes["hash"]; $hash = $this->changes["hash"];

View file

@ -39,4 +39,25 @@ trait TSubscribable
$sub->delete(); $sub->delete();
return false; 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"); 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 function getSubscriptions(int $page = 1, int $limit = 6): \Traversable
{ {
return $this->_abstractRelationGenerator("get-subscriptions-user", $page, $limit); return $this->_abstractRelationGenerator("get-subscriptions-user", $page, $limit);

View file

@ -23,4 +23,13 @@ class APITokens extends Repository
return $token; 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(); return $alias->getUser();
} }
function getByChandlerUserId(string $cid): ?User
{
return $this->toUser($this->users->where("user", $cid)->fetch());
}
function getByChandlerUser(?ChandlerUser $user): ?User 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 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 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 LEFT JOIN
(SELECT target FROM subscriptions WHERE follower=? AND model="openvk\\Web\\Models\\Entities\\User") u1 (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 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 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")); $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) private function searchResults(object $repo, &$count)
{ {
$query = $this->queryParam("q") ?? ""; $query = $this->queryParam("q") ?? "";
@ -76,7 +83,7 @@ final class AdminPresenter extends OpenVKPresenter
function renderIndex(): void function renderIndex(): void
{ {
$this->warnIfLongpoolBroken();
} }
function renderUsers(): void function renderUsers(): void
@ -154,6 +161,7 @@ final class AdminPresenter extends OpenVKPresenter
$club->setShortCode($this->postParam("shortcode")); $club->setShortCode($this->postParam("shortcode"));
$club->setVerified(empty($this->postParam("verify") ? 0 : 1)); $club->setVerified(empty($this->postParam("verify") ? 0 : 1));
$club->setHide_From_Global_Feed(empty($this->postParam("hide_from_global_feed") ? 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(); $club->save();
break; break;
case "ban": case "ban":
@ -681,7 +689,8 @@ final class AdminPresenter extends OpenVKPresenter
$this->template->obj_type = $obj_type; $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(); $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->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->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->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") ?? ""; $website = $this->postParam("website") ?? "";
if(empty($website)) if(empty($website))

View file

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

View file

@ -234,8 +234,14 @@ final class VKAPIPresenter extends OpenVKPresenter
} }
try { try {
// Проверка типа параметра
$type = $parameter->getType();
if (($type && !$type->isBuiltin()) || is_null($val)) {
$params[] = $val;
} else {
settype($val, $parameter->getType()->getName()); settype($val, $parameter->getType()->getName());
$params[] = $val; $params[] = $val;
}
} catch (\Throwable $e) { } catch (\Throwable $e) {
// Just ignore the exception, since // Just ignore the exception, since
// some args are intended for internal use // some args are intended for internal use
@ -286,17 +292,31 @@ final class VKAPIPresenter extends OpenVKPresenter
$this->fail(28, "Invalid 2FA code", "internal", "acquireToken"); $this->fail(28, "Invalid 2FA code", "internal", "acquireToken");
} }
$token = NULL;
$tokenIsStale = true;
$platform = $this->requestParam("client_name"); $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 APITokens)->getStaleByUser($uId, $platform);
}
if(is_null($token)) {
$tokenIsStale = false;
$token = new APIToken; $token = new APIToken;
$token->setUser($user); $token->setUser($user);
$token->setPlatform($platform ?? (new WhichBrowser\Parser(getallheaders()))->toString()); $token->setPlatform($platform ?? (new WhichBrowser\Parser(getallheaders()))->toString());
$token->save(); $token->save();
}
$payload = json_encode([ $payload = json_encode([
"access_token" => $token->getFormattedToken(), "access_token" => $token->getFormattedToken(),
"expires_in" => 0, "expires_in" => 0,
"user_id" => $uId, "user_id" => $uId,
"is_stale" => $tokenIsStale,
]); ]);
$size = strlen($payload); $size = strlen($payload);
@ -304,4 +324,42 @@ final class VKAPIPresenter extends OpenVKPresenter
header("Content-Length: $size"); header("Content-Length: $size");
exit($payload); 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="/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="{$thisUser->getURL()}" class="link" title="{_my_page} [Alt+Shift+.]" accesskey=".">{_my_page}</a>
<a href="/friends{$thisUser->getId()}" class="link">{_my_friends} <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"> <a href="/friends{$thisUser->getId()}?act=incoming" class="linkunderline">
(<b>{$thisUser->getFollowersCount()}</b>) (<b>{$thisUser->getRequestsCount()}</b>)
</a> </a>
</object> </object>
</a> </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('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 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} <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>) (<b>{$thisUser->getNotificationsCount()}</b>)
{/if} </object>
</a> </a>
<a n:if="$thisUser->getLeftMenuItemStatus('apps')" href="/apps?act=installed" class="link">{_my_apps}</a> <a n:if="$thisUser->getLeftMenuItemStatus('apps')" href="/apps?act=installed" class="link">{_my_apps}</a>
<a href="/settings" class="link">{_my_settings}</a> <a href="/settings" class="link">{_my_settings}</a>
@ -405,13 +405,6 @@
{script "js/al_notifs.js"} {script "js/al_notifs.js"}
{/ifset} {/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>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> <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} {include description, x => $dat}
{/ifset} {/ifset}
</td> </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} {include actions, x => $dat}
</td> </td>
</tr> </tr>

View file

@ -255,17 +255,6 @@
Disabled Disabled
</td> </td>
</tr> </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> <tr>
<td class="e"> <td class="e">
NDA Test Label NDA Test Label

View file

@ -58,13 +58,17 @@
</div> </div>
<br/> <br/>
<div class="group"> <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> <label for="verify">{_admin_verification}</label>
</div> </div>
<div class="group"> <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> <label for="hide_from_global_feed">{_admin_club_excludeglobalfeed}</label>
</div> </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/> <hr/>
<div class="buttons-container"> <div class="buttons-container">
<div class="buttons"> <div class="buttons">

View file

@ -83,7 +83,7 @@
<option value="0" n:attr="selected => $club->getWallType() == 0" /> {_group_closed_post}</option> <option value="0" n:attr="selected => $club->getWallType() == 0" /> {_group_closed_post}</option>
<select> <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> </td>
</tr> </tr>
<tr> <tr>

View file

@ -54,8 +54,8 @@
<table> <table>
<tbody> <tbody>
<tr> <tr>
<td width="120" valign="top"><span class="nobold">{_gender}: </span></td> <td width="120" valign="top"><span class="nobold">{_pronouns}: </span></td>
<td>{$user->isFemale() ? tr("female"): tr("male")}</td> <td>{$x->isFemale() ? tr("female") : ($x->isNeutral() ? tr("neutral") : tr("male"))}</td>
</tr> </tr>
<tr> <tr>
<td width="120" valign="top"><span class="nobold">{_registration_date}: </span></td> <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"> <form n:if="$report->getContentType() != 'group'" action="/admin/reportAction{$report->getId()}" method="post">
<input type="hidden" name="hash" value="{$csrfToken}"/> <input type="hidden" name="hash" value="{$csrfToken}"/>
<input type="submit" name="ban" value="{_ban_user_action}" class="button"> <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"> <input type="submit" name="ignore" value="{_ignore_report}" class="button">
</form> </form>
<form n:if="$report->getContentType() == 'group'" action="/admin/reportAction{$report->getId()}" method="post"> <form n:if="$report->getContentType() == 'group'" action="/admin/reportAction{$report->getId()}" method="post">

View file

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

View file

@ -427,6 +427,22 @@ h1 {
text-transform: lowercase; 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>a,
.profile_link.disable { .profile_link.disable {
cursor: not-allowed; cursor: not-allowed;
@ -587,6 +603,11 @@ input[type=radio]:hover {
background-position: 0 -28px; background-position: 0 -28px;
} }
input[type=checkbox]:disabled {
background-position: 0 -28px;
cursor: initial;
}
input[type=checkbox]:checked, input[type=checkbox]:checked,
input[type=radio]:checked { input[type=radio]:checked {
background-position: 0 -14px; background-position: 0 -14px;
@ -597,6 +618,10 @@ input[type=radio]:checked:hover {
background-position: 0 -42px; background-position: 0 -42px;
} }
input[type=checkbox]:checked:disabled {
background-position: 0 -42px;
}
#auth { #auth {
padding: 10px; padding: 10px;
} }
@ -2059,20 +2084,17 @@ table td[width="120"] {
font-weight: bold; font-weight: bold;
margin-right: 10px; margin-right: 10px;
display: inline-block; display: inline-block;
border-radius: 2px;
} }
.mb_tab div { .mb_tab div {
padding: 3px 7px; padding: 5px 9px;
} }
.mb_tab#active { .mb_tab#active {
background-color: #898989; background-color: #898989;
} }
.mb_tab#active div {
border: 2px solid #5f5f5f;
}
.mb_tab#active a { .mb_tab#active a {
color: white; color: white;
} }

View file

@ -167,6 +167,23 @@ document.addEventListener("DOMContentLoaded", function() { //BEGIN
return false; 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 }); //END ONREADY DECLS
async function repostPost(id, hash) { 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")); $sessionOffset = intval(Session::i()->get("_timezoneOffset"));
$str = strftime($format, $timestamp + ($sessionOffset * MINUTE) * -1 ?? time() + ($sessionOffset * MINUTE) * -1, tr("__locale") !== '@__locale' ? tr("__locale") : NULL); $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"); $enc = tr("__WinEncoding");
if($enc === "@__WinEncoding") if($enc === "@__WinEncoding")
$enc = "Windows-1251"; $enc = "Windows-1251";
@ -232,7 +232,7 @@ function ovk_is_ssl(): bool
return $GLOBALS["requestIsSSL"]; return $GLOBALS["requestIsSSL"];
} }
function parseAttachments(string $attachments) function parseAttachments(string $attachments): array
{ {
$attachmentsArr = explode(",", $attachments); $attachmentsArr = explode(",", $attachments);
$returnArr = []; $returnArr = [];
@ -251,7 +251,8 @@ function parseAttachments(string $attachments)
$attachmentIds = str_replace($attachmentType, "", $attachment); $attachmentIds = str_replace($attachmentType, "", $attachment);
$attachmentOwner = (int) explode("_", $attachmentIds)[0]; $attachmentOwner = (int) explode("_", $attachmentIds)[0];
$attachmentId = (int)end(explode("_", $attachmentIds)); $gatoExplotano = explode("_", $attachmentIds);
$attachmentId = (int) end($gatoExplotano);
switch($attachmentType) { switch($attachmentType) {
case "photo": case "photo":

View file

@ -2,7 +2,6 @@
"require": { "require": {
"php": "~7.3||~8.1", "php": "~7.3||~8.1",
"guzzlehttp/guzzle": "^6.5", "guzzlehttp/guzzle": "^6.5",
"komeiji-satori/curl": "dev-master",
"whichbrowser/parser": "dev-master", "whichbrowser/parser": "dev-master",
"james-heinrich/getid3": "^1.9@dev", "james-heinrich/getid3": "^1.9@dev",
"rybakit/msgpack": "dev-master", "rybakit/msgpack": "dev-master",
@ -11,7 +10,7 @@
"ezyang/htmlpurifier": "dev-master", "ezyang/htmlpurifier": "dev-master",
"scssphp/scssphp": "dev-main", "scssphp/scssphp": "dev-main",
"lfkeitel/phptotp": "dev-master", "lfkeitel/phptotp": "dev-master",
"chillerlan/php-qrcode": "dev-main", "chillerlan/php-qrcode": "5.0.2",
"vearutop/php-obscene-censor-rus": "dev-master", "vearutop/php-obscene-censor-rus": "dev-master",
"erusev/parsedown": "dev-master", "erusev/parsedown": "dev-master",
"bhaktaraz/php-rss-generator": "dev-master", "bhaktaraz/php-rss-generator": "dev-master",
@ -20,7 +19,8 @@
"symfony/console": "5.4.x-dev", "symfony/console": "5.4.x-dev",
"wapmorgan/morphos": "dev-master", "wapmorgan/morphos": "dev-master",
"ext-sodium": "*", "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" caption: "Ad caption"
link: "https://example.org/product.aspx?id=10&from=ovk" link: "https://example.org/product.aspx?id=10&from=ovk"
bellsAndWhistles: bellsAndWhistles:
fartscroll: false
testLabel: false testLabel: false
defaultMobileTheme: "" defaultMobileTheme: ""

View file

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

View file

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

View file

@ -97,7 +97,6 @@ data:
caption: "Ad caption" caption: "Ad caption"
link: "https://example.org/product.aspx?id=10&from=ovk" link: "https://example.org/product.aspx?id=10&from=ovk"
bellsAndWhistles: bellsAndWhistles:
fartscroll: false
testLabel: false testLabel: false
defaultMobileTheme: "" 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_delete" = "Выдаліць з сяброў";
"friends_reject" = "Адмяніць заяўку"; "friends_reject" = "Адмяніць заяўку";
"friends_accept" = "Прыняць заяўку"; "friends_accept" = "Прыняць заяўку";
"friends_leave_in_flw" = "Пакінуть у падпісчыках";
"send_message" = "Адправіць паведамленне"; "send_message" = "Адправіць паведамленне";
"incoming_req" = "Падпісанты"; "incoming_req" = "Падпісанты";
"outcoming_req" = "Заяўкі"; "outcoming_req" = "Заяўкі";

View file

@ -184,10 +184,10 @@
"post_writes_g" = "published"; "post_writes_g" = "published";
"post_deact_m" = "deleted his profile saying:"; "post_deact_m" = "deleted his profile saying:";
"post_deact_f" = "deleted her 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_m" = "silently deleted his profile.";
"post_deact_silent_f" = "silently deleted her 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_your_wall" = "on your wall";
"post_on_group_wall" = "in $1"; "post_on_group_wall" = "in $1";
"post_on_user_wall" = "on $1's wall"; "post_on_user_wall" = "on $1's wall";
@ -259,6 +259,10 @@
"friends_delete" = "Remove from friends"; "friends_delete" = "Remove from friends";
"friends_reject" = "Reject request"; "friends_reject" = "Reject request";
"friends_accept" = "Accept 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"; "send_message" = "Send a message";
"incoming_req" = "Pending"; "incoming_req" = "Pending";
"outcoming_req" = "Outgoing"; "outcoming_req" = "Outgoing";
@ -481,6 +485,7 @@
"upd_m" = "updated his profile picture"; "upd_m" = "updated his profile picture";
"upd_f" = "updated her profile picture"; "upd_f" = "updated her profile picture";
"upd_n" = "updated their profile picture";
"upd_g" = "updated group's picture"; "upd_g" = "updated group's picture";
"add_photos" = "Add photos"; "add_photos" = "Add photos";
@ -777,6 +782,15 @@
"disable_2fa" = "Turn off 2FA"; "disable_2fa" = "Turn off 2FA";
"viewing" = "View"; "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 */ /* Sorting */
"sort_randomly" = "Sort randomly"; "sort_randomly" = "Sort randomly";
@ -832,7 +846,7 @@
"limits" = "Limits"; "limits" = "Limits";
"select_audio" = "Select audio from your computer"; "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"; "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 among the files you have already downloaded using";
"search_audio_inst" = "audios search"; "search_audio_inst" = "audios search";
@ -840,7 +854,7 @@
"audio_embed_not_found" = "Audio not found"; "audio_embed_not_found" = "Audio not found";
"audio_embed_deleted" = "Audio was deleted"; "audio_embed_deleted" = "Audio was deleted";
"audio_embed_withdrawn" = "The audio was withdrawn at the request of the copyright holder"; "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."; "audio_embed_processing" = "Audio is still being processed, or has not been processed correctly.";
"audios_count_zero" = "No audios"; "audios_count_zero" = "No audios";
@ -1190,6 +1204,7 @@
"report_number" = "Report #"; "report_number" = "Report #";
"list_of_reports" = "List of reports"; "list_of_reports" = "List of reports";
"text_of_the_post" = "Text of the post"; "text_of_the_post" = "Text of the post";
"delete_content" = "Delete content";
"today" = "today"; "today" = "today";
"will_be_watched" = "It will be reviewed by the moderators soon"; "will_be_watched" = "It will be reviewed by the moderators soon";
@ -1582,6 +1597,7 @@
"admin_user_online_deceased" = "Deceased"; "admin_user_online_deceased" = "Deceased";
"admin_club_search" = "Search for groups"; "admin_club_search" = "Search for groups";
"admin_club_excludeglobalfeed" = "Do not display posts in the global feed"; "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_services" = "Paid services";
"admin_newgift" = "New gift"; "admin_newgift" = "New gift";
@ -1617,6 +1633,9 @@
"admin_commerce_disabled" = "Commerce has been disabled by the system administrator"; "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_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_links" = "Blocked links";
"admin_banned_link" = "Link"; "admin_banned_link" = "Link";
"admin_banned_domain" = "Domain"; "admin_banned_domain" = "Domain";
@ -1700,7 +1719,7 @@
"about_wall_posts_one" = "<b>1</b> wall post"; "about_wall_posts_one" = "<b>1</b> wall post";
"about_wall_posts_other" = "<b>$1</b> wall posts"; "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 */ /* Dialogs */
@ -1910,9 +1929,9 @@
"tour_section_11_title_1" = "Themes"; "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_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_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_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_title_1" = "Profile and Group Backgrounds";
"tour_section_12_text_1" = "You can set two images as the background of your page."; "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_title_1" = "Տեսքեր";
"tour_section_11_text_1" = "Գրանցվելուց հետո Ձեր էջում կիրառվում է սովորական տեսքը"; "tour_section_11_text_1" = "Գրանցվելուց հետո Ձեր էջում կիրառվում է սովորական տեսքը";
"tour_section_11_text_2" = "Որոշ նորեկները կարող է չսիրեն լռելյայն տեսքը, քանի որ այն անգամ հնության զգացում է տալիս"; "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_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_title_1" = "Պրոֆիլ և խմբի ետնապատկերներ";
"tour_section_12_text_1" = "Դուք կարող եք երկու ետնապատկեր տեղադրել"; "tour_section_12_text_1" = "Դուք կարող եք երկու ետնապատկեր տեղադրել";

View file

@ -239,6 +239,10 @@
"friends_delete" = "Удалить из друзей"; "friends_delete" = "Удалить из друзей";
"friends_reject" = "Отменить заявку"; "friends_reject" = "Отменить заявку";
"friends_accept" = "Принять заявку"; "friends_accept" = "Принять заявку";
"friends_leave_in_flw" = "Оставить в подписчиках";
"friends_add_msg" = "Теперь вы друзья.";
"friends_rej_msg" = "Вы оставили пользователя в подписчиках.";
"friends_rem_msg" = "Вы удалили пользователя из списка своих друзей.";
"send_message" = "Отправить сообщение"; "send_message" = "Отправить сообщение";
"incoming_req" = "Входящие"; "incoming_req" = "Входящие";
"outcoming_req" = "Исходящие"; "outcoming_req" = "Исходящие";
@ -739,6 +743,15 @@
"disable_2fa" = "Отключить 2FA"; "disable_2fa" = "Отключить 2FA";
"viewing" = "Просмотреть"; "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 */ /* Sorting */
"sort_randomly" = "Сортировать случайно"; "sort_randomly" = "Сортировать случайно";
@ -1123,6 +1136,7 @@
"report_number" = "Жалоба №"; "report_number" = "Жалоба №";
"list_of_reports" = "Список жалоб"; "list_of_reports" = "Список жалоб";
"text_of_the_post" = "Текст записи"; "text_of_the_post" = "Текст записи";
"delete_content" = "Удалить контент";
"today" = "сегодня"; "today" = "сегодня";
"will_be_watched" = "Скоро её рассмотрят модераторы"; "will_be_watched" = "Скоро её рассмотрят модераторы";
@ -1479,6 +1493,7 @@
"admin_user_online_deceased" = "Покойник"; "admin_user_online_deceased" = "Покойник";
"admin_club_search" = "Поиск групп"; "admin_club_search" = "Поиск групп";
"admin_club_excludeglobalfeed" = "Не отображать записи в глобальной ленте"; "admin_club_excludeglobalfeed" = "Не отображать записи в глобальной ленте";
"admin_club_enforceexcludeglobalfeed" = "Запретить руководству группы изменять отображение в глобальной ленте";
"admin_services" = "Платные услуги"; "admin_services" = "Платные услуги";
"admin_newgift" = "Новый подарок"; "admin_newgift" = "Новый подарок";
"admin_price" = "Цена"; "admin_price" = "Цена";
@ -1509,6 +1524,8 @@
"admin_about_instance" = "Инстанция"; "admin_about_instance" = "Инстанция";
"admin_commerce_disabled" = "Коммерция отключена системным администратором"; "admin_commerce_disabled" = "Коммерция отключена системным администратором";
"admin_commerce_disabled_desc" = "Настройки ваучеров и подарков будут сохранены, но не будут оказывать никакого влияния."; "admin_commerce_disabled_desc" = "Настройки ваучеров и подарков будут сохранены, но не будут оказывать никакого влияния.";
"admin_longpool_broken" = "Longpool сломан!";
"admin_longpool_broken_desc" = "Проверьте, существует ли файл по пути <code>$1</code> и выданы ли у него правильные права на запись.";
"admin_banned_links" = "Заблокированные ссылки"; "admin_banned_links" = "Заблокированные ссылки";
"admin_banned_link" = "Ссылка"; "admin_banned_link" = "Ссылка";
"admin_banned_domain" = "Домен"; "admin_banned_domain" = "Домен";
@ -1802,9 +1819,9 @@
"tour_section_11_title_1" = "Темы оформления"; "tour_section_11_title_1" = "Темы оформления";
"tour_section_11_text_1" = "После регистрации, в качестве оформления у вас будет установлена стандартная тема"; "tour_section_11_text_1" = "После регистрации, в качестве оформления у вас будет установлена стандартная тема";
"tour_section_11_text_2" = "Некоторых новых пользователей может слегка отпугнуть нынешняя стоковая тема, которая веет совсем уж древностью"; "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_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_title_1" = "Фон профиля и группы";
"tour_section_12_text_1" = "Вы можете установить два изображения в качестве фона вашей страницы"; "tour_section_12_text_1" = "Вы можете установить два изображения в качестве фона вашей страницы";

View file

@ -1669,9 +1669,9 @@
"tour_section_11_title_1" = "Temy oformlenija"; "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_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_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_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_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"; "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_delete" = "Видалити з друзів";
"friends_reject" = "Скасувати заявку"; "friends_reject" = "Скасувати заявку";
"friends_accept" = "Прийняти заявку"; "friends_accept" = "Прийняти заявку";
"friends_leave_in_flw" = "Залишити у підписниках";
"send_message" = "Відправити повідомлення"; "send_message" = "Відправити повідомлення";
"incoming_req" = "Підписники"; "incoming_req" = "Підписники";
"outcoming_req" = "Вихідні"; "outcoming_req" = "Вихідні";
@ -1706,9 +1707,9 @@
"tour_section_11_title_1" = "Теми оформлення"; "tour_section_11_title_1" = "Теми оформлення";
"tour_section_11_text_1" = "Після реєстрації, як стандартна тема, у вас буде класична тема оформлення"; "tour_section_11_text_1" = "Після реєстрації, як стандартна тема, у вас буде класична тема оформлення";
"tour_section_11_text_2" = "Деяких нових користувачів може налякати чинна класична тема, яка виглядає дуже архаїчно"; "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_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_title_1" = "Фон профілю та групи";
"tour_section_12_text_1" = "Ви можете встановити одну чи два зображення як фон вашої сторінки"; "tour_section_12_text_1" = "Ви можете встановити одну чи два зображення як фон вашої сторінки";

View file

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

View file

@ -1,7 +1,7 @@
.page_header { .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 { .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; color-scheme: dark !important;
} }
body, #backdropDripper, #standaloneCommentBox { body,
#backdropDripper,
#standaloneCommentBox,
.ovk-photo-view {
background-color: #0e0b1a; background-color: #0e0b1a;
color: #c6d2e8; 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%); 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; color: #8b9ab5 !important;
} }
.nobold, nobold { .nobold,
nobold {
color: #6f82a8; color: #6f82a8;
} }
@ -31,15 +40,103 @@ span, .post-author .date, .crp-entry--message---text, .messenger-app--messages--
color: #8eb2d0; color: #8eb2d0;
} }
.wrap1, .wrap2, .page-wrap, #wrapH, #wrapHI { .wrap1,
.wrap2,
.page-wrap,
#wrapH,
#wrapHI {
border-color: #1c202f; 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; 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-top-color: #1e1a2b;
border-bottom-color: #1e1a2b; border-bottom-color: #1e1a2b;
} }
@ -53,7 +150,13 @@ hr {
box-shadow: unset; 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; background-color: #383052;
} }
@ -61,7 +164,9 @@ hr {
background-color: #40375e; background-color: #40375e;
} }
.menu_divider, .ovk-diag-action, .minilink .counter { .menu_divider,
.ovk-diag-action,
.minilink .counter {
background-color: #2c2640; background-color: #2c2640;
} }
@ -70,11 +175,14 @@ hr {
border-color: #2c2640; border-color: #2c2640;
} }
.bsdn_contextMenuElement:hover, .searchList li:hover { .bsdn_contextMenuElement:hover,
.searchList li:hover {
background-color: #29223a; 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; background-color: #453e5e !important;
} }
@ -82,19 +190,35 @@ hr {
background-color: #272e4894; background-color: #272e4894;
} }
a, .page_footer .link, #profile_link, .profile_link { a,
.page_footer .link,
#profile_link,
.profile_link {
color: #8fb9d8; 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; background-color: #272138 !important;
} }
.header_navigation .link a, .searchOptionName { .header_navigation .link a,
.searchOptionName {
color: #bcc3d0; color: #bcc3d0;
} }
.header_navigation .link a:hover, .home_button_custom { .header_navigation .link a:hover,
.home_button_custom {
color: #c7cdd9; color: #c7cdd9;
} }
@ -107,7 +231,8 @@ a, .page_footer .link, #profile_link, .profile_link {
color: #7b94c4 !important; color: #7b94c4 !important;
} }
#test-label, .msg.msg_err { #test-label,
.msg.msg_err {
background-color: #30161d; background-color: #30161d;
} }
@ -115,19 +240,47 @@ a, .page_footer .link, #profile_link, .profile_link {
background-color: #163f13; background-color: #163f13;
} }
h4, .content_title_expanded, .summaryBar .summary, .content_title_unexpanded { h4,
.content_title_expanded,
.summaryBar .summary,
.content_title_unexpanded {
color: #7c94c5; color: #7c94c5;
} }
.notes_titles small, .post-upload, .post-has-poll { .notes_titles small,
.post-upload,
.post-has-poll {
color: #6f82a8; 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; 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; background-color: #1e1a2b !important;
} }
@ -137,22 +290,27 @@ h4, .content_title_expanded, .summaryBar .summary, .content_title_unexpanded {
} }
.content_title_expanded { .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 { .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; 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; background-color: #120e1f;
} }
#wallAttachmentMenu > .header, .messenger-app--messages---message.unread, tr.h { #wallAttachmentMenu>.header,
.messenger-app--messages---message.unread,
tr.h {
background-color: #1d192b; background-color: #1d192b;
} }
@ -163,41 +321,59 @@ h4, .content_title_expanded, .summaryBar .summary, .content_title_unexpanded {
.page_yellowheader { .page_yellowheader {
color: #c6d2e8; 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; background-color: #231f34;
border-color: #231f34; border-color: #231f34;
} }
.page_header { .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 { .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; color: #a48aff !important;
} }
.completeness-gauge, .poll-result-bar { .completeness-gauge,
.poll-result-bar {
background-color: #231e33; background-color: #231e33;
} }
.completeness-gauge > div, .poll-result-bar-sub { .completeness-gauge>div,
.poll-result-bar-sub {
background-color: #2c2640; 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; background-color: #181826 !important;
} }
input[type="checkbox"] { 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"] { 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 { .header_navigation .link {
@ -205,19 +381,20 @@ input[type="radio"] {
} }
.heart { .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 { .pinned-mark,
background-image: url("/themepack/midnight/0.0.2.8/resource/pin.png") !important; .post-author .pin {
background-image: url("/themepack/midnight/0.0.2.9/resource/pin.png") !important;
} }
.repost-icon { .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 { .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 { .user-alert {
@ -239,7 +416,7 @@ input[type="radio"] {
} }
#backdropEditor { #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; border-color: #473e66 !important;
} }
@ -260,11 +437,13 @@ input[type="radio"] {
background-color: rgb(30, 26, 43) !important; background-color: rgb(30, 26, 43) !important;
} }
.bigPlayer .selectableTrack, .audioEmbed .track > .selectableTrack { .bigPlayer .selectableTrack,
.audioEmbed .track>.selectableTrack {
border-top: #b9b9b9 1px solid !important; border-top: #b9b9b9 1px solid !important;
} }
.bigPlayer .paddingLayer .slider, .audioEmbed .track .slider { .bigPlayer .paddingLayer .slider,
.audioEmbed .track .slider {
background: #b9b9b9 !important; background: #b9b9b9 !important;
} }
@ -323,7 +502,8 @@ input[type="radio"] {
filter: invert(81%); 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%); filter: invert(100%);
} }
@ -339,7 +519,8 @@ img[src$='/assets/packages/static/openvk/img/camera_200.png'], img[src$='/assets
color: unset !important; color: unset !important;
} }
#upload_container, .whiteBox { #upload_container,
.whiteBox {
background: #1d1928 !important; background: #1d1928 !important;
border: 1px solid #383052 !important; border: 1px solid #383052 !important;
} }
@ -375,7 +556,8 @@ ul {
cursor: pointer; cursor: pointer;
} }
.showMore, .showMoreAudiosPlaylist { .showMore,
.showMoreAudiosPlaylist {
background: #181826 !important; background: #181826 !important;
} }
@ -383,6 +565,7 @@ ul {
.rightNav h1 { .rightNav h1 {
background: #000; background: #000;
} }
.tabcontent { .tabcontent {
background: #2c2640 !important; background: #2c2640 !important;
} }

View file

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