mirror of
https://github.com/openvk/openvk
synced 2025-07-07 00:09:48 +03:00
Compare commits
11 commits
4915824085
...
134a47ff95
Author | SHA1 | Date | |
---|---|---|---|
|
134a47ff95 | ||
|
c8a97f8b8d | ||
|
93b1202a13 | ||
|
4f126d1b05 | ||
|
27fb923178 | ||
|
79e2446184 | ||
|
5ecb69e880 | ||
|
a32ce9f941 | ||
|
b77103627f | ||
|
b552d26af5 | ||
|
4235883af3 |
35 changed files with 673 additions and 391 deletions
|
@ -98,6 +98,10 @@ final class Friends extends VKAPIRequestHandler
|
||||||
|
|
||||||
switch ($user->getSubscriptionStatus($this->getUser())) {
|
switch ($user->getSubscriptionStatus($this->getUser())) {
|
||||||
case 0:
|
case 0:
|
||||||
|
if (\openvk\Web\Util\EventRateLimiter::i()->tryToLimit($this->getUser(), "friends.outgoing_sub")) {
|
||||||
|
$this->failTooOften();
|
||||||
|
}
|
||||||
|
|
||||||
$user->toggleSubscription($this->getUser());
|
$user->toggleSubscription($this->getUser());
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,10 @@ final class Gifts extends VKAPIRequestHandler
|
||||||
$this->fail(-105, "Commerce is disabled on this instance");
|
$this->fail(-105, "Commerce is disabled on this instance");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (\openvk\Web\Util\EventRateLimiter::i()->tryToLimit($this->getUser(), "gifts.send", false)) {
|
||||||
|
$this->failTooOften();
|
||||||
|
}
|
||||||
|
|
||||||
$user = (new UsersRepo())->get((int) $user_ids); # FAKE прогноз погоды (в данном случае user_ids)
|
$user = (new UsersRepo())->get((int) $user_ids); # FAKE прогноз погоды (в данном случае user_ids)
|
||||||
|
|
||||||
if (!$user || $user->isDeleted()) {
|
if (!$user || $user->isDeleted()) {
|
||||||
|
|
|
@ -312,6 +312,10 @@ final class Groups extends VKAPIRequestHandler
|
||||||
$isMember = !is_null($this->getUser()) ? (int) $club->getSubscriptionStatus($this->getUser()) : 0;
|
$isMember = !is_null($this->getUser()) ? (int) $club->getSubscriptionStatus($this->getUser()) : 0;
|
||||||
|
|
||||||
if ($isMember == 0) {
|
if ($isMember == 0) {
|
||||||
|
if (\openvk\Web\Util\EventRateLimiter::i()->tryToLimit($this->getUser(), "groups.sub")) {
|
||||||
|
$this->failTooOften();
|
||||||
|
}
|
||||||
|
|
||||||
$club->toggleSubscription($this->getUser());
|
$club->toggleSubscription($this->getUser());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -317,6 +317,32 @@ final class Users extends VKAPIRequestHandler
|
||||||
|
|
||||||
$response[$i]->custom_fields = $append_array;
|
$response[$i]->custom_fields = $append_array;
|
||||||
break;
|
break;
|
||||||
|
case "bdate":
|
||||||
|
if (!$canView) {
|
||||||
|
$response[$i]->bdate = "01.01.1970";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$visibility = $usr->getBirthdayPrivacy();
|
||||||
|
$response[$i]->bdate_visibility = $visibility;
|
||||||
|
|
||||||
|
$birthday = $usr->getBirthday();
|
||||||
|
if ($birthday) {
|
||||||
|
switch ($visibility) {
|
||||||
|
case 1:
|
||||||
|
$response[$i]->bdate = $birthday->format('%d.%m');
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
$response[$i]->bdate = $birthday->format('%d.%m.%Y');
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
default:
|
||||||
|
$response[$i]->bdate = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$response[$i]->bdate = null;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,11 @@ abstract class VKAPIRequestHandler
|
||||||
throw new APIErrorException($message, $code);
|
throw new APIErrorException($message, $code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function failTooOften(): never
|
||||||
|
{
|
||||||
|
$this->fail(9, "Rate limited");
|
||||||
|
}
|
||||||
|
|
||||||
protected function getUser(): ?User
|
protected function getUser(): ?User
|
||||||
{
|
{
|
||||||
return $this->user;
|
return $this->user;
|
||||||
|
|
|
@ -713,6 +713,10 @@ final class Wall extends VKAPIRequestHandler
|
||||||
$post->setSuggested(1);
|
$post->setSuggested(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (\openvk\Web\Util\EventRateLimiter::i()->tryToLimit($this->getUser(), "wall.post")) {
|
||||||
|
$this->failTooOften();
|
||||||
|
}
|
||||||
|
|
||||||
$post->save();
|
$post->save();
|
||||||
} catch (\LogicException $ex) {
|
} catch (\LogicException $ex) {
|
||||||
$this->fail(100, "One of the parameters specified was missing or invalid");
|
$this->fail(100, "One of the parameters specified was missing or invalid");
|
||||||
|
@ -723,7 +727,7 @@ final class Wall extends VKAPIRequestHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($owner_id > 0 && $owner_id !== $this->getUser()->getId()) {
|
if ($owner_id > 0 && $owner_id !== $this->getUser()->getId()) {
|
||||||
(new WallPostNotification($wallOwner, $post, $this->user->identity))->emit();
|
(new WallPostNotification($wallOwner, $post, $this->getUser()))->emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
return (object) ["post_id" => $post->getVirtualId()];
|
return (object) ["post_id" => $post->getVirtualId()];
|
||||||
|
@ -873,6 +877,8 @@ final class Wall extends VKAPIRequestHandler
|
||||||
"id" => $comment->getId(),
|
"id" => $comment->getId(),
|
||||||
"from_id" => $oid,
|
"from_id" => $oid,
|
||||||
"date" => $comment->getPublicationTime()->timestamp(),
|
"date" => $comment->getPublicationTime()->timestamp(),
|
||||||
|
"can_edit" => $post->canBeEditedBy($this->getUser()),
|
||||||
|
"can_delete" => $post->canBeDeletedBy($this->getUser()),
|
||||||
"text" => $comment->getText(false),
|
"text" => $comment->getText(false),
|
||||||
"post_id" => $post->getVirtualId(),
|
"post_id" => $post->getVirtualId(),
|
||||||
"owner_id" => method_exists($post, 'isPostedOnBehalfOfGroup') && $post->isPostedOnBehalfOfGroup() ? $post->getOwner()->getId() * -1 : $post->getOwner()->getId(),
|
"owner_id" => method_exists($post, 'isPostedOnBehalfOfGroup') && $post->isPostedOnBehalfOfGroup() ? $post->getOwner()->getId() * -1 : $post->getOwner()->getId(),
|
||||||
|
|
|
@ -176,11 +176,13 @@ class Post extends Postable
|
||||||
$platform = $this->getRecord()->api_source_name;
|
$platform = $this->getRecord()->api_source_name;
|
||||||
if ($forAPI) {
|
if ($forAPI) {
|
||||||
switch ($platform) {
|
switch ($platform) {
|
||||||
|
case 'openvk_native':
|
||||||
case 'openvk_refresh_android':
|
case 'openvk_refresh_android':
|
||||||
case 'openvk_legacy_android':
|
case 'openvk_legacy_android':
|
||||||
return 'android';
|
return 'android';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'openvk_native_ios':
|
||||||
case 'openvk_ios':
|
case 'openvk_ios':
|
||||||
case 'openvk_legacy_ios':
|
case 'openvk_legacy_ios':
|
||||||
return 'iphone';
|
return 'iphone';
|
||||||
|
|
|
@ -34,9 +34,9 @@ trait TSubscribable
|
||||||
"target" => $this->getId(),
|
"target" => $this->getId(),
|
||||||
];
|
];
|
||||||
$sub = $ctx->table("subscriptions")->where($data);
|
$sub = $ctx->table("subscriptions")->where($data);
|
||||||
|
|
||||||
if (!($sub->fetch())) {
|
if (!($sub->fetch())) {
|
||||||
$ctx->table("subscriptions")->insert($data);
|
$ctx->table("subscriptions")->insert($data);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -971,11 +971,13 @@ class User extends RowModel
|
||||||
$platform = $this->getRecord()->client_name;
|
$platform = $this->getRecord()->client_name;
|
||||||
if ($forAPI) {
|
if ($forAPI) {
|
||||||
switch ($platform) {
|
switch ($platform) {
|
||||||
|
case 'openvk_native':
|
||||||
case 'openvk_refresh_android':
|
case 'openvk_refresh_android':
|
||||||
case 'openvk_legacy_android':
|
case 'openvk_legacy_android':
|
||||||
return 'android';
|
return 'android';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'openvk_native_ios':
|
||||||
case 'openvk_ios':
|
case 'openvk_ios':
|
||||||
case 'openvk_legacy_ios':
|
case 'openvk_legacy_ios':
|
||||||
return 'iphone';
|
return 'iphone';
|
||||||
|
@ -1738,4 +1740,52 @@ class User extends RowModel
|
||||||
{
|
{
|
||||||
return DatabaseConnection::i()->getContext()->table("blacklist_relations")->where("author", $this->getId())->count();
|
return DatabaseConnection::i()->getContext()->table("blacklist_relations")->where("author", $this->getId())->count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getEventCounters(array $list): array
|
||||||
|
{
|
||||||
|
$count_of_keys = sizeof(array_keys($list));
|
||||||
|
$ev_str = $this->getRecord()->events_counters;
|
||||||
|
$counters = [];
|
||||||
|
|
||||||
|
if (!$ev_str) {
|
||||||
|
for ($i = 0; $i < sizeof(array_keys($list)); $i++) {
|
||||||
|
$counters[] = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$counters = unpack("S" . $count_of_keys, base64_decode($ev_str, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'counters' => array_combine(array_keys($list), $counters),
|
||||||
|
'refresh_time' => $this->getRecord()->events_refresh_time,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stateEvents(array $state_list): void
|
||||||
|
{
|
||||||
|
$pack_str = "";
|
||||||
|
|
||||||
|
foreach ($state_list as $item => $id) {
|
||||||
|
$pack_str .= "S";
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->stateChanges("events_counters", base64_encode(pack($pack_str, ...array_values($state_list))));
|
||||||
|
|
||||||
|
if (!$this->getRecord()->events_refresh_time) {
|
||||||
|
$this->stateChanges("events_refresh_time", time());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function resetEvents(array $list): void
|
||||||
|
{
|
||||||
|
$values = [];
|
||||||
|
|
||||||
|
foreach ($list as $key => $val) {
|
||||||
|
$values[$key] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->stateEvents($values);
|
||||||
|
$this->stateChanges("events_refresh_time", time());
|
||||||
|
$this->save();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,6 +147,29 @@ final class AboutPresenter extends OpenVKPresenter
|
||||||
$this->redirect("https://github.com/openvk/openvk#readme");
|
$this->redirect("https://github.com/openvk/openvk#readme");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function renderAssetLinksJSON(): void
|
||||||
|
{
|
||||||
|
# Необходимо любому андроид приложению для автоматического разрешения принимать ссылки с этого сайта.
|
||||||
|
# Не шарю как писать норм на php поэтому тут чутка на вайбкодил - искренне ваш, ZAZiOs.
|
||||||
|
header("Content-Type: application/json");
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
[
|
||||||
|
"relation" => ["delegate_permission/common.handle_all_urls"],
|
||||||
|
"target" => [
|
||||||
|
"namespace" => "android_app",
|
||||||
|
"package_name" => "oss.OpenVK.Native",
|
||||||
|
"sha256_cert_fingerprints" => [
|
||||||
|
"79:67:14:23:DC:6E:FA:49:64:1F:F1:81:0E:B0:A3:AE:6E:88:AB:0D:CF:BC:02:96:F3:6D:76:6B:82:94:D6:9C",
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
echo json_encode($data, JSON_UNESCAPED_SLASHES);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
public function renderDev(): void
|
public function renderDev(): void
|
||||||
{
|
{
|
||||||
$this->redirect("https://docs.ovk.to/");
|
$this->redirect("https://docs.ovk.to/");
|
||||||
|
|
|
@ -106,6 +106,10 @@ final class GiftsPresenter extends OpenVKPresenter
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (\openvk\Web\Util\EventRateLimiter::i()->tryToLimit($this->user->identity, "gifts.send")) {
|
||||||
|
$this->flashFail("err", tr("error"), tr("limit_exceed_exception"));
|
||||||
|
}
|
||||||
|
|
||||||
$comment = empty($c = $this->postParam("comment")) ? null : $c;
|
$comment = empty($c = $this->postParam("comment")) ? null : $c;
|
||||||
$notification = new GiftNotification($user, $this->user->identity, $gift, $comment);
|
$notification = new GiftNotification($user, $this->user->identity, $gift, $comment);
|
||||||
$notification->emit();
|
$notification->emit();
|
||||||
|
|
|
@ -68,6 +68,10 @@ final class GroupPresenter extends OpenVKPresenter
|
||||||
$club->setAbout(empty($this->postParam("about")) ? null : $this->postParam("about"));
|
$club->setAbout(empty($this->postParam("about")) ? null : $this->postParam("about"));
|
||||||
$club->setOwner($this->user->id);
|
$club->setOwner($this->user->id);
|
||||||
|
|
||||||
|
if (\openvk\Web\Util\EventRateLimiter::i()->tryToLimit($this->user->identity, "groups.create")) {
|
||||||
|
$this->flashFail("err", tr("error"), tr("limit_exceed_exception"));
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$club->save();
|
$club->save();
|
||||||
} catch (\PDOException $ex) {
|
} catch (\PDOException $ex) {
|
||||||
|
@ -79,6 +83,7 @@ final class GroupPresenter extends OpenVKPresenter
|
||||||
}
|
}
|
||||||
|
|
||||||
$club->toggleSubscription($this->user->identity);
|
$club->toggleSubscription($this->user->identity);
|
||||||
|
|
||||||
$this->redirect("/club" . $club->getId());
|
$this->redirect("/club" . $club->getId());
|
||||||
} else {
|
} else {
|
||||||
$this->flashFail("err", tr("error"), tr("error_no_group_name"));
|
$this->flashFail("err", tr("error"), tr("error_no_group_name"));
|
||||||
|
@ -103,6 +108,12 @@ final class GroupPresenter extends OpenVKPresenter
|
||||||
$this->flashFail("err", tr("error"), tr("forbidden"));
|
$this->flashFail("err", tr("error"), tr("forbidden"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$club->getSubscriptionStatus($this->user->identity)) {
|
||||||
|
if (\openvk\Web\Util\EventRateLimiter::i()->tryToLimit($this->user->identity, "groups.sub")) {
|
||||||
|
$this->flashFail("err", tr("error"), tr("limit_exceed_exception"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$club->toggleSubscription($this->user->identity);
|
$club->toggleSubscription($this->user->identity);
|
||||||
|
|
||||||
$this->redirect($club->getURL());
|
$this->redirect($club->getURL());
|
||||||
|
|
|
@ -103,6 +103,10 @@ final class ReportPresenter extends OpenVKPresenter
|
||||||
exit(json_encode([ "error" => "You can't report yourself" ]));
|
exit(json_encode([ "error" => "You can't report yourself" ]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->user->identity->isBannedInSupport()) {
|
||||||
|
exit(json_encode([ "reason" => $this->queryParam("reason") ]));
|
||||||
|
}
|
||||||
|
|
||||||
if (in_array($this->queryParam("type"), ["post", "photo", "video", "group", "comment", "note", "app", "user", "audio", "doc"])) {
|
if (in_array($this->queryParam("type"), ["post", "photo", "video", "group", "comment", "note", "app", "user", "audio", "doc"])) {
|
||||||
if (count(iterator_to_array($this->reports->getDuplicates($this->queryParam("type"), $id, null, $this->user->id))) <= 0) {
|
if (count(iterator_to_array($this->reports->getDuplicates($this->queryParam("type"), $id, null, $this->user->id))) <= 0) {
|
||||||
$report = new Report();
|
$report = new Report();
|
||||||
|
|
|
@ -418,6 +418,12 @@ final class UserPresenter extends OpenVKPresenter
|
||||||
if ($this->postParam("act") == "rej") {
|
if ($this->postParam("act") == "rej") {
|
||||||
$user->changeFlags($this->user->identity, 0b10000000, true);
|
$user->changeFlags($this->user->identity, 0b10000000, true);
|
||||||
} else {
|
} else {
|
||||||
|
if ($user->getSubscriptionStatus($this->user->identity) == \openvk\Web\Models\Entities\User::SUBSCRIPTION_ABSENT) {
|
||||||
|
if (\openvk\Web\Util\EventRateLimiter::i()->tryToLimit($this->user->identity, "friends.outgoing_sub")) {
|
||||||
|
$this->flashFail("err", tr("error"), tr("limit_exceed_exception"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$user->toggleSubscription($this->user->identity);
|
$user->toggleSubscription($this->user->identity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -356,6 +356,10 @@ final class WallPresenter extends OpenVKPresenter
|
||||||
$this->flashFail("err", tr("failed_to_publish_post"), tr("post_is_empty_or_too_big"));
|
$this->flashFail("err", tr("failed_to_publish_post"), tr("post_is_empty_or_too_big"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (\openvk\Web\Util\EventRateLimiter::i()->tryToLimit($this->user->identity, "wall.post")) {
|
||||||
|
$this->flashFail("err", tr("error"), tr("limit_exceed_exception"));
|
||||||
|
}
|
||||||
|
|
||||||
$should_be_suggested = $wall < 0 && !$wallOwner->canBeModifiedBy($this->user->identity) && $wallOwner->getWallType() == 2;
|
$should_be_suggested = $wall < 0 && !$wallOwner->canBeModifiedBy($this->user->identity) && $wallOwner->getWallType() == 2;
|
||||||
try {
|
try {
|
||||||
$post = new Post();
|
$post = new Post();
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
<span class="nobold">{_"2fa_code_2"}: </span>
|
<span class="nobold">{_"2fa_code_2"}: </span>
|
||||||
</td>
|
</td>
|
||||||
<td class="regform-right">
|
<td class="regform-right">
|
||||||
<input id="password" type="password" name="password" required />
|
<input id="password" type="number" autocomplete="off" name="password" required />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
<span class="nobold">{_code}: </span>
|
<span class="nobold">{_code}: </span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="text" name="code" autocomplete="off" required autofocus />
|
<input type="number" name="code" autocomplete="off" required autofocus />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
@ -67,7 +67,7 @@
|
||||||
},
|
},
|
||||||
success: (response) => {
|
success: (response) => {
|
||||||
if (response?.reports?.length != _content) {
|
if (response?.reports?.length != _content) {
|
||||||
NewNotification("Обратите внимание", "В списке появились новые жалобы. Работа ждёт :)");
|
// NewNotification("Обратите внимание", "В списке появились новые жалобы. Работа ждёт :)");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response.reports.length > 0) {
|
if (response.reports.length > 0) {
|
||||||
|
|
|
@ -33,6 +33,18 @@
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block size}
|
{block size}
|
||||||
|
{if !is_null($thisUser) && $user->getId() === $thisUser->getId()}
|
||||||
|
<div id="groups_graybar" class="container_gray">
|
||||||
|
<form action="/search" id="search_box">
|
||||||
|
<input name="section" type="hidden" value="groups">
|
||||||
|
<input name="q" class="header_search_input" value="" style="width: 320px" placeholder="{_search_by_groups}">
|
||||||
|
</form>
|
||||||
|
<form action="/groups_create" id="create_group">
|
||||||
|
<button class="button">{_create_group}</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<div style="padding-bottom: 0px; {if is_null($thisUser) || $user->getId() !== $thisUser->getId()}padding-top: 0px;{/if}" class="summaryBar">
|
<div style="padding-bottom: 0px; {if is_null($thisUser) || $user->getId() !== $thisUser->getId()}padding-top: 0px;{/if}" class="summaryBar">
|
||||||
<div class="summary">
|
<div class="summary">
|
||||||
{if !is_null($thisUser) && $user->getId() === $thisUser->getId()}
|
{if !is_null($thisUser) && $user->getId() === $thisUser->getId()}
|
||||||
|
@ -107,26 +119,3 @@
|
||||||
</form>
|
</form>
|
||||||
{/if}
|
{/if}
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block bottom}
|
|
||||||
{if !is_null($thisUser) && $user->getId() === $thisUser->getId()}
|
|
||||||
<div class="groups_options">
|
|
||||||
<div id="gp_container" style="width: 200px; margin-right: 39px;">
|
|
||||||
<h4>{_open_new_group}</h4>
|
|
||||||
<span>{_open_group_desc}</span>
|
|
||||||
<form action="/groups_create">
|
|
||||||
<button class="button">{_create_group}</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<div id="gp_container" style="width: 344px;">
|
|
||||||
<h4>{_search_group}</h4>
|
|
||||||
<span>{_search_group_desc}</span>
|
|
||||||
<form action="/search">
|
|
||||||
<input name="section" type="hidden" value="groups">
|
|
||||||
<input name="q" class="header_search_input" value="" style="background: none; width: 155px; padding-left: 3px;">
|
|
||||||
<button class="button">{_search_by_groups}</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{/block}
|
|
|
@ -72,7 +72,7 @@
|
||||||
<span class="nobold">{_"2fa_code"}</span>
|
<span class="nobold">{_"2fa_code"}</span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="text" name="email_change_code" style="width: 100%;" />
|
<input type="number" autocomplete="off" name="email_change_code" style="width: 100%;" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -161,7 +161,7 @@
|
||||||
<span class="nobold">{_"2fa_code"}</span>
|
<span class="nobold">{_"2fa_code"}</span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="text" name="password_change_code" style="width: 100%;" />
|
<input type="number" autocomplete="off" name="password_change_code" style="width: 100%;" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
95
Web/Util/EventRateLimiter.php
Normal file
95
Web/Util/EventRateLimiter.php
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace openvk\Web\Util;
|
||||||
|
|
||||||
|
use openvk\Web\Models\Entities\User;
|
||||||
|
use openvk\Web\Models\RowModel;
|
||||||
|
use Chandler\Patterns\TSimpleSingleton;
|
||||||
|
|
||||||
|
class EventRateLimiter
|
||||||
|
{
|
||||||
|
use TSimpleSingleton;
|
||||||
|
|
||||||
|
private $config;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->config = OPENVK_ROOT_CONF["openvk"]["preferences"]["security"]["rateLimits"]["eventsLimit"];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function tryToLimit(?User $user, string $event_type, bool $is_update = true): bool
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Checks count of actions for last x seconds
|
||||||
|
|
||||||
|
Uses OPENVK_ROOT_CONF["openvk"]["preferences"]["security"]["rateLimits"]["eventsLimit"]
|
||||||
|
|
||||||
|
This check should be peformed only after checking other conditions cuz by default it increments counter
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
true — limit has exceed and the action must be restricted
|
||||||
|
|
||||||
|
false — the action can be performed
|
||||||
|
|
||||||
|
Also returns "true" if this option is disabled
|
||||||
|
*/
|
||||||
|
|
||||||
|
$isEnabled = $this->config['enable'];
|
||||||
|
$isIgnoreForAdmins = $this->config['ignoreForAdmins'];
|
||||||
|
$restrictionTime = $this->config['restrictionTime'];
|
||||||
|
$eventsList = $this->config['list'];
|
||||||
|
|
||||||
|
if (!$isEnabled) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($isIgnoreForAdmins && $user->isAdmin()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$eventsStats = $user->getEventCounters($eventsList);
|
||||||
|
$limitForThatEvent = $eventsList[$event_type];
|
||||||
|
|
||||||
|
$counters = $eventsStats["counters"];
|
||||||
|
$refresh_time = $eventsStats["refresh_time"];
|
||||||
|
$is_restrict_over = $refresh_time < (time() - $restrictionTime);
|
||||||
|
$event_counter = $counters[$event_type];
|
||||||
|
|
||||||
|
if ($refresh_time && $is_restrict_over) {
|
||||||
|
$user->resetEvents($eventsList);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$is_limit_exceed = $event_counter >= $limitForThatEvent;
|
||||||
|
|
||||||
|
if (!$is_limit_exceed && $is_update) {
|
||||||
|
$this->incrementEvent($counters, $event_type, $user);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $is_limit_exceed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function incrementEvent(array $old_values, string $event_type, User $initiator): bool
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Updates counter for user
|
||||||
|
*/
|
||||||
|
$isEnabled = $this->config['enable'];
|
||||||
|
$eventsList = $this->config['list'];
|
||||||
|
|
||||||
|
if (!$isEnabled) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$old_values[$event_type] += 1;
|
||||||
|
|
||||||
|
$initiator->stateEvents($old_values);
|
||||||
|
$initiator->save();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -407,6 +407,8 @@ routes:
|
||||||
handler: "About->robotsTxt"
|
handler: "About->robotsTxt"
|
||||||
- url: "/humans.txt"
|
- url: "/humans.txt"
|
||||||
handler: "About->humansTxt"
|
handler: "About->humansTxt"
|
||||||
|
- url: "/.well-known/assetlinks.json"
|
||||||
|
handler: "About->AssetLinksJSON"
|
||||||
- url: "/dev"
|
- url: "/dev"
|
||||||
handler: "About->dev"
|
handler: "About->dev"
|
||||||
- url: "/iapi/getPhotosFromPost/{num}_{num}"
|
- url: "/iapi/getPhotosFromPost/{num}_{num}"
|
||||||
|
|
|
@ -2211,17 +2211,12 @@ body.scrolled .toTop:hover, .toTop.has_down:hover {
|
||||||
border-top: #DEDEDE solid 1px;
|
border-top: #DEDEDE solid 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#gp_container {
|
#groups_graybar form {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
#gp_container span {
|
#groups_graybar #create_group {
|
||||||
display: block;
|
float: right;
|
||||||
margin: 10px 0 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#gp_container h4 {
|
|
||||||
font-size: 11px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.container_gray .content:last-child {
|
.container_gray .content:last-child {
|
||||||
|
@ -2854,7 +2849,7 @@ a.poll-retract-vote {
|
||||||
padding: 11px 4px 0 7px;
|
padding: 11px 4px 0 7px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header_navigation #search_box input[type='search'] {
|
#search_box input[type='search'] {
|
||||||
height: 20px;
|
height: 20px;
|
||||||
background: url('/assets/packages/static/openvk/img/search_icon.png') no-repeat 3px 4px;
|
background: url('/assets/packages/static/openvk/img/search_icon.png') no-repeat 3px 4px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
|
|
BIN
Web/static/img/app_icons/openvk_native.png
Normal file
BIN
Web/static/img/app_icons/openvk_native.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 37 KiB |
|
@ -3,4 +3,6 @@
|
||||||
<Client tag="vk4me" name="VK4ME" url="http://vk4me.crx.moe/" img="/assets/packages/static/openvk/img/app_icons/vk4me.png" />
|
<Client tag="vk4me" name="VK4ME" url="http://vk4me.crx.moe/" img="/assets/packages/static/openvk/img/app_icons/vk4me.png" />
|
||||||
<Client tag="openvk_legacy_android" name="OpenVK Legacy" url="https://f-droid.org/packages/uk.openvk.android.legacy/" img="/assets/packages/static/openvk/img/app_icons/openvk_legacy.png" />
|
<Client tag="openvk_legacy_android" name="OpenVK Legacy" url="https://f-droid.org/packages/uk.openvk.android.legacy/" img="/assets/packages/static/openvk/img/app_icons/openvk_legacy.png" />
|
||||||
<Client tag="openvk_refresh_android" name="OpenVK Refresh" url="https://github.com/openvk/mobile-android-refresh" img="/assets/packages/static/openvk/img/app_icons/openvk_refresh.png" />
|
<Client tag="openvk_refresh_android" name="OpenVK Refresh" url="https://github.com/openvk/mobile-android-refresh" img="/assets/packages/static/openvk/img/app_icons/openvk_refresh.png" />
|
||||||
|
<Client tag="openvk_native" name="OpenVK Native" url="https://ovk.to/club9628" img="/assets/packages/static/openvk/img/app_icons/openvk_native.png" />
|
||||||
|
<Client tag="openvk_native_ios" name="OpenVK Native" url="https://ovk.to/club9628" img="/assets/packages/static/openvk/img/app_icons/openvk_native.png" />
|
||||||
</Clients>
|
</Clients>
|
3
install/sqls/00057-event-limiting.sql
Normal file
3
install/sqls/00057-event-limiting.sql
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
ALTER TABLE `profiles`
|
||||||
|
ADD `events_counters` VARCHAR(299) NULL DEFAULT NULL AFTER `audio_broadcast_enabled`,
|
||||||
|
ADD `events_refresh_time` BIGINT(20) UNSIGNED NULL DEFAULT NULL AFTER `events_counters`;
|
|
@ -480,11 +480,7 @@
|
||||||
"meetings_one" = "$1 meeting";
|
"meetings_one" = "$1 meeting";
|
||||||
"meetings_other" = "$1 meetings";
|
"meetings_other" = "$1 meetings";
|
||||||
|
|
||||||
"open_new_group" = "Start a New Group";
|
|
||||||
"open_group_desc" = "Unable to find the perfect group? Start your own...";
|
|
||||||
"search_group" = "Search for a Group";
|
|
||||||
"search_by_groups" = "Explore Groups";
|
"search_by_groups" = "Explore Groups";
|
||||||
"search_group_desc" = "Browse through existing groups and find the one that suits your needs...";
|
|
||||||
|
|
||||||
"error_suggestions" = "Error accessing to suggestions";
|
"error_suggestions" = "Error accessing to suggestions";
|
||||||
"error_suggestions_closed" = "This group has closed wall.";
|
"error_suggestions_closed" = "This group has closed wall.";
|
||||||
|
@ -1657,6 +1653,8 @@
|
||||||
"error_geolocation" = "Error while trying to pin geolocation";
|
"error_geolocation" = "Error while trying to pin geolocation";
|
||||||
"error_no_geotag" = "There is no geo-tag pinned in this post";
|
"error_no_geotag" = "There is no geo-tag pinned in this post";
|
||||||
|
|
||||||
|
"limit_exceed_exception" = "You're doing this action too often. Try again later.";
|
||||||
|
|
||||||
/* Admin actions */
|
/* Admin actions */
|
||||||
|
|
||||||
"login_as" = "Login as $1";
|
"login_as" = "Login as $1";
|
||||||
|
|
|
@ -329,11 +329,7 @@
|
||||||
"meetings_one" = "Մեկ հանդիպում";
|
"meetings_one" = "Մեկ հանդիպում";
|
||||||
"meetings_other" = "$1 հանդիպում";
|
"meetings_other" = "$1 հանդիպում";
|
||||||
|
|
||||||
"open_new_group" = "Նոր խումբ բացել";
|
|
||||||
"open_group_desc" = "Չե՞ք կարողանում գտնել ճիշտ խումբը, բացե՛ք ձերը․․․";
|
|
||||||
"search_group" = "Խմբի որոնում";
|
|
||||||
"search_by_groups" = "Որոնում ըստ խմբերի";
|
"search_by_groups" = "Որոնում ըստ խմբերի";
|
||||||
"search_group_desc" = "Այստեղ դուք կարող եք փնտրել խմբեր և ընտրել ձեզ ամենահարմարը․․․";
|
|
||||||
|
|
||||||
/* Albums */
|
/* Albums */
|
||||||
|
|
||||||
|
|
|
@ -290,11 +290,7 @@
|
||||||
"meetings_one" = "$1 rapat/pertemuan";
|
"meetings_one" = "$1 rapat/pertemuan";
|
||||||
"meetings_other" = "$1 rapat/pertemuan";
|
"meetings_other" = "$1 rapat/pertemuan";
|
||||||
|
|
||||||
"open_new_group" = "Open a new group";
|
"search_by_groups" = "Cari grup";
|
||||||
"open_group_desc" = "Can't find the right group? Open your own...";
|
|
||||||
"search_group" = "Cari grup";
|
|
||||||
"search_by_groups" = "Search by groups";
|
|
||||||
"search_group_desc" = "Here you can browse through the existing groups and choose a group to suit your needs...";
|
|
||||||
|
|
||||||
/* Albums */
|
/* Albums */
|
||||||
|
|
||||||
|
|
|
@ -289,11 +289,7 @@
|
||||||
"meetings_zero" = "Кездесулер жоқ";
|
"meetings_zero" = "Кездесулер жоқ";
|
||||||
"meetings_one" = "$1 кездесу";
|
"meetings_one" = "$1 кездесу";
|
||||||
"meetings_other" = "$1 кездесу";
|
"meetings_other" = "$1 кездесу";
|
||||||
"open_new_group" = "Жаңа топ ашу";
|
|
||||||
"open_group_desc" = "Өзіңізге сай топ таба алмай жүрсіз бе? Өзіңіз ашып алыңыз!";
|
|
||||||
"search_group" = "Топ іздеу";
|
|
||||||
"search_by_groups" = "Топтардан іздеу";
|
"search_by_groups" = "Топтардан іздеу";
|
||||||
"search_group_desc" = "Мұнда сіз бар топтарға шолу жасай аласыз және қажеттіліктеріңізге сай топты таңдай аласыз.";
|
|
||||||
|
|
||||||
/* Albums */
|
/* Albums */
|
||||||
|
|
||||||
|
|
|
@ -465,11 +465,7 @@
|
||||||
"meetings_few" = "$1 встречи";
|
"meetings_few" = "$1 встречи";
|
||||||
"meetings_many" = "$1 встреч";
|
"meetings_many" = "$1 встреч";
|
||||||
"meetings_other" = "$1 встреч";
|
"meetings_other" = "$1 встреч";
|
||||||
"open_new_group" = "Открыть новую группу";
|
|
||||||
"open_group_desc" = "Не можете найти нужную группу? Откройте свою...";
|
|
||||||
"search_group" = "Поиск группы";
|
|
||||||
"search_by_groups" = "Поиск по группам";
|
"search_by_groups" = "Поиск по группам";
|
||||||
"search_group_desc" = "Здесь Вы можете просмотреть существующие группы и выбрать группу себе по вкусу...";
|
|
||||||
"group_banned" = "К сожалению, нам пришлось заблокировать сообщество <b>$1</b>.";
|
"group_banned" = "К сожалению, нам пришлось заблокировать сообщество <b>$1</b>.";
|
||||||
|
|
||||||
"error_suggestions" = "Ошибка доступа к предложенным";
|
"error_suggestions" = "Ошибка доступа к предложенным";
|
||||||
|
@ -1462,7 +1458,7 @@
|
||||||
"error_access_denied_short" = "Ошибка доступа";
|
"error_access_denied_short" = "Ошибка доступа";
|
||||||
"error_access_denied" = "У вас недостаточно прав, чтобы редактировать этот ресурс";
|
"error_access_denied" = "У вас недостаточно прав, чтобы редактировать этот ресурс";
|
||||||
"success" = "Успешно";
|
"success" = "Успешно";
|
||||||
"comment_will_not_appear" = "Этот комментарий больше не будет показыватся.";
|
"comment_will_not_appear" = "Этот комментарий больше не будет показываться.";
|
||||||
|
|
||||||
"error_when_gifting" = "Не удалось подарить";
|
"error_when_gifting" = "Не удалось подарить";
|
||||||
"error_user_not_exists" = "Пользователь или набор не существуют.";
|
"error_user_not_exists" = "Пользователь или набор не существуют.";
|
||||||
|
@ -1561,6 +1557,8 @@
|
||||||
"error_geolocation" = "Ошибка при прикреплении геометки";
|
"error_geolocation" = "Ошибка при прикреплении геометки";
|
||||||
"error_no_geotag" = "У поста не указана гео-метка";
|
"error_no_geotag" = "У поста не указана гео-метка";
|
||||||
|
|
||||||
|
"limit_exceed_exception" = "Вы совершаете это действие слишком часто. Повторите позже.";
|
||||||
|
|
||||||
/* Admin actions */
|
/* Admin actions */
|
||||||
|
|
||||||
"login_as" = "Войти как $1";
|
"login_as" = "Войти как $1";
|
||||||
|
|
|
@ -319,11 +319,7 @@
|
||||||
"meetings_few" = "$1 vstreči";
|
"meetings_few" = "$1 vstreči";
|
||||||
"meetings_many" = "$1 vstreč";
|
"meetings_many" = "$1 vstreč";
|
||||||
"meetings_other" = "$1 vstreč";
|
"meetings_other" = "$1 vstreč";
|
||||||
"open_new_group" = "Otkrytí novuju gruppu";
|
|
||||||
"open_group_desc" = "Ne možete najti nužnuju gruppu? Otkrojte svoju...";
|
|
||||||
"search_group" = "Poisk gruppy";
|
|
||||||
"search_by_groups" = "Poisk po gruppam";
|
"search_by_groups" = "Poisk po gruppam";
|
||||||
"search_group_desc" = "Zdesí Vy možete prosmotretí susčestvujusčie gruppy i vybratí gruppu sebe po vkusu...";
|
|
||||||
"group_banned" = "K sožaleniju, nam prišlosí zablokirovatí soobsčestvo <b>$1</b>.";
|
"group_banned" = "K sožaleniju, nam prišlosí zablokirovatí soobsčestvo <b>$1</b>.";
|
||||||
|
|
||||||
/* Albums */
|
/* Albums */
|
||||||
|
|
|
@ -442,11 +442,7 @@
|
||||||
"meetings_few" = "$1 зустрічі";
|
"meetings_few" = "$1 зустрічі";
|
||||||
"meetings_many" = "$1 зустрічей";
|
"meetings_many" = "$1 зустрічей";
|
||||||
"meetings_other" = "$1 зустрічей";
|
"meetings_other" = "$1 зустрічей";
|
||||||
"open_new_group" = "Створити нову спільноту";
|
|
||||||
"open_group_desc" = "Не можете знайти потрібну спільноту? Відкрийте свою!";
|
|
||||||
"search_group" = "Пошук спільнот";
|
|
||||||
"search_by_groups" = "Пошук за спільнотами";
|
"search_by_groups" = "Пошук за спільнотами";
|
||||||
"search_group_desc" = "Тут Ви можете переглянути існуючі спільноти та обрати спільноту до вподоби.";
|
|
||||||
"group_banned" = "Спільнота <b>$1</b> заблокована.";
|
"group_banned" = "Спільнота <b>$1</b> заблокована.";
|
||||||
"error_suggestions" = "Помилка доступу до пропозиційної";
|
"error_suggestions" = "Помилка доступу до пропозиційної";
|
||||||
"error_suggestions_closed" = "Ця спільнота має закриту стіну.";
|
"error_suggestions_closed" = "Ця спільнота має закриту стіну.";
|
||||||
|
|
|
@ -41,6 +41,16 @@ openvk:
|
||||||
maxViolations: 50
|
maxViolations: 50
|
||||||
maxViolationsAge: 120
|
maxViolationsAge: 120
|
||||||
autoban: true
|
autoban: true
|
||||||
|
eventsLimit:
|
||||||
|
enable: true
|
||||||
|
ignoreForAdmins: true
|
||||||
|
restrictionTime: 86400
|
||||||
|
list:
|
||||||
|
groups.create: 5
|
||||||
|
groups.sub: 50
|
||||||
|
friends.outgoing_sub: 25
|
||||||
|
wall.post: 5000
|
||||||
|
gifts.send: 30
|
||||||
blacklists:
|
blacklists:
|
||||||
limit: 100
|
limit: 100
|
||||||
applyToAdmins: true
|
applyToAdmins: true
|
||||||
|
|
|
@ -1,30 +1,35 @@
|
||||||
body {
|
body {
|
||||||
background: url("/themepack/openvk_modern/0.0.1.0/resource/1.png") repeat-x fixed;
|
background: url("/themepack/openvk_modern/0.0.1.0/resource/1.png") repeat-x
|
||||||
|
fixed;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page_header {
|
.page_header {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
height: 42px;
|
height: 42px;
|
||||||
background: #3C3C3C;
|
background: #3c3c3c;
|
||||||
z-index: 199;
|
z-index: 199;
|
||||||
}
|
}
|
||||||
|
|
||||||
.home_button {
|
.home_button {
|
||||||
background: #3C3C3C url("/themepack/openvk_modern/0.0.1.0/resource/2.png") no-repeat;
|
background: #3c3c3c url("/themepack/openvk_modern/0.0.1.0/resource/2.png")
|
||||||
|
no-repeat;
|
||||||
background-size: 80%;
|
background-size: 80%;
|
||||||
background-position-y: 0px;
|
background-position-y: 0px;
|
||||||
background-position-x: 1px;
|
background-position-x: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.home_button_custom {
|
.home_button_custom {
|
||||||
background: #3C3C3C url("/themepack/openvk_modern/0.0.1.0/resource/4.png") no-repeat;
|
background: #3c3c3c url("/themepack/openvk_modern/0.0.1.0/resource/4.png")
|
||||||
|
no-repeat;
|
||||||
background-size: 80%;
|
background-size: 80%;
|
||||||
background-position-y: 0px;
|
background-position-y: 0px;
|
||||||
background-position-x: 1px;
|
background-position-x: 1px;
|
||||||
|
width: 145px !important;
|
||||||
text-shadow: none;
|
text-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header_navigation .link, .header_navigation .header_divider_stick {
|
.header_navigation .link,
|
||||||
|
.header_navigation .header_divider_stick {
|
||||||
background: unset !important;
|
background: unset !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,9 +37,21 @@ body {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.header_navigation #search_box .search_box_button {
|
||||||
|
border: solid 1px #606060;
|
||||||
|
box-shadow: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_navigation #search_box .search_box_button:active {
|
||||||
|
background-color: #606060;
|
||||||
|
box-shadow: unset;
|
||||||
|
}
|
||||||
|
|
||||||
.sidebar {
|
.sidebar {
|
||||||
margin-top: 47px;
|
margin-top: 47px;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
background-color: #fff;
|
||||||
|
z-index: 199;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page_body {
|
.page_body {
|
||||||
|
@ -59,15 +76,15 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.content_subtitle {
|
.content_subtitle {
|
||||||
border-top: #F0F0F0 solid 1px;
|
border-top: #f0f0f0 solid 1px;
|
||||||
border-bottom: 1px solid #F0F0F0;
|
border-bottom: 1px solid #f0f0f0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-alert {
|
.user-alert {
|
||||||
border: 1px solid #f3ddbd;
|
border: 1px solid #f3ddbd;
|
||||||
}
|
}
|
||||||
|
|
||||||
.msg {
|
.msg {
|
||||||
border: 1pt solid #e6f2f3;
|
border: 1pt solid #e6f2f3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,15 +97,18 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.navigation .link:hover {
|
.navigation .link:hover {
|
||||||
border-top: 1px solid #E4E4E4;
|
border-top: 1px solid #e4e4e4;
|
||||||
}
|
}
|
||||||
|
|
||||||
#profile_link, .profile_link {
|
#profile_link,
|
||||||
|
.profile_link {
|
||||||
border-bottom: 1px solid transparent;
|
border-bottom: 1px solid transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.completeness-gauge-gold {
|
.completeness-gauge {
|
||||||
border: 1px solid #f6ebbb;
|
width: 100%;
|
||||||
|
border: unset;
|
||||||
|
border-top: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
.post-author {
|
.post-author {
|
||||||
|
@ -103,18 +123,18 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.page_yellowheader {
|
.page_yellowheader {
|
||||||
background: #E2E2E2;
|
background: #e2e2e2;
|
||||||
border-right: solid 1px #E2E2E2;
|
border-right: solid 1px #e2e2e2;
|
||||||
border-left: solid 1px #E2E2E2;
|
border-left: solid 1px #e2e2e2;
|
||||||
border-bottom: solid 1px #E2E2E2;
|
border-bottom: solid 1px #e2e2e2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page_yellowheader span {
|
.page_yellowheader span {
|
||||||
color: #BBBBBB;
|
color: #bbbbbb;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page_yellowheader a {
|
.page_yellowheader a {
|
||||||
color: #5C5C5C;
|
color: #5c5c5c;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-wrap {
|
.page-wrap {
|
||||||
|
@ -130,8 +150,8 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
#wrapHI {
|
#wrapHI {
|
||||||
border-right: solid 1px #E2E2E2;
|
border-right: solid 1px #e2e2e2;
|
||||||
border-left: solid 1px #E2E2E2;
|
border-left: solid 1px #e2e2e2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.left_small_block {
|
.left_small_block {
|
||||||
|
@ -139,40 +159,59 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu_divider {
|
.menu_divider {
|
||||||
background: #E5E5E5;
|
background: #e5e5e5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.postFeedWrapper {
|
.postFeedWrapper {
|
||||||
border-bottom: 1px solid rgb(240,240,240);
|
border-bottom: 1px solid rgb(240, 240, 240);
|
||||||
}
|
}
|
||||||
|
|
||||||
.container_gray {
|
.container_gray {
|
||||||
border-top: #EBEBEB solid 1px;
|
border-top: #ebebeb solid 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.container_gray .content {
|
.container_gray .content {
|
||||||
border: #E5E5E5 solid 1px;
|
border: #e5e5e5 solid 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.accent-box {
|
.accent-box {
|
||||||
border: 1px solid white;
|
border: 1px solid white;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="text"], input[type="password"], input[type~="text"],
|
input[type="text"],
|
||||||
input[type~="password"], input[type="email"], input[type="phone"],
|
input[type="password"],
|
||||||
input[type~="email"], input[type~="phone"], input[type="date"],
|
input[type~="text"],
|
||||||
input[type~="date"], input[type="search"], input[type~="search"],
|
input[type~="password"],
|
||||||
textarea, select {
|
input[type="email"],
|
||||||
border: 1px solid #E5E5E5;
|
input[type="phone"],
|
||||||
|
input[type~="email"],
|
||||||
|
input[type~="phone"],
|
||||||
|
input[type="date"],
|
||||||
|
input[type~="date"],
|
||||||
|
input[type="search"],
|
||||||
|
input[type~="search"],
|
||||||
|
textarea,
|
||||||
|
select {
|
||||||
|
border: 1px solid #e5e5e5;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type=checkbox] {
|
input[type="checkbox"] {
|
||||||
background-image: url("/themepack/openvk_modern/0.0.1.0/resource/6.png")
|
background-image: url("/themepack/openvk_modern/0.0.1.0/resource/6.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
list-style-type: disc;
|
list-style-type: disc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.like_tooltip_wrapper .like_tooltip_head {
|
||||||
|
background: #515151;
|
||||||
|
box-shadow: unset;
|
||||||
|
border: solid 1px #515151;
|
||||||
|
}
|
||||||
|
|
||||||
|
.like_tooltip_wrapper .like_tooltip_body {
|
||||||
|
border: 1px solid #515151;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mb_tab#active div {
|
.mb_tab#active div {
|
||||||
|
@ -197,20 +236,20 @@ ul {
|
||||||
}
|
}
|
||||||
|
|
||||||
.crp-entry:first-of-type {
|
.crp-entry:first-of-type {
|
||||||
border-color: #E5E5E5;
|
border-color: #e5e5e5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.crp-entry {
|
.crp-entry {
|
||||||
width: 593px;
|
width: 593px;
|
||||||
border-color: #E5E5E5;
|
border-color: #e5e5e5;
|
||||||
}
|
}
|
||||||
|
|
||||||
#faqhead {
|
#faqhead {
|
||||||
border: 1px solid #FBF3C3;
|
border: 1px solid #fbf3c3;
|
||||||
}
|
}
|
||||||
|
|
||||||
#faqcontent {
|
#faqcontent {
|
||||||
border: 1px solid #FAFAFA;
|
border: 1px solid #fafafa;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ovk-diag {
|
.ovk-diag {
|
||||||
|
@ -233,23 +272,25 @@ ul {
|
||||||
border-bottom-right-radius: 2px;
|
border-bottom-right-radius: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#votesBalance {
|
#votesBalance,
|
||||||
border-bottom: none;
|
#news {
|
||||||
|
border-bottom: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
.floating_sidebar,.floating_sidebar.show {
|
.floating_sidebar,
|
||||||
display:none
|
.floating_sidebar.show {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#backdrop:before {
|
#backdrop:before {
|
||||||
content:"";
|
content: "";
|
||||||
display:block;
|
display: block;
|
||||||
position:fixed;
|
position: fixed;
|
||||||
top:0;
|
top: 0;
|
||||||
left:0;
|
left: 0;
|
||||||
height:42px;
|
height: 42px;
|
||||||
width:100%;
|
width: 100%;
|
||||||
background-color:#3c3c3c
|
background-color: #3c3c3c;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search_box_button {
|
.search_box_button {
|
||||||
|
@ -276,6 +317,7 @@ ul {
|
||||||
|
|
||||||
.verticalGrayTabsWrapper {
|
.verticalGrayTabsWrapper {
|
||||||
border-top: unset;
|
border-top: unset;
|
||||||
|
border-left: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sugglist {
|
.sugglist {
|
||||||
|
@ -291,11 +333,13 @@ ul {
|
||||||
filter: contrast(2) !important;
|
filter: contrast(2) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.audioEmbed .track > .selectableTrack, .bigPlayer .selectableTrack {
|
.audioEmbed .track > .selectableTrack,
|
||||||
|
.bigPlayer .selectableTrack {
|
||||||
border-top: #404040 1px solid !important;
|
border-top: #404040 1px solid !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bigPlayer .paddingLayer .slider, .audioEmbed .track .slider {
|
.bigPlayer .paddingLayer .slider,
|
||||||
|
.audioEmbed .track .slider {
|
||||||
background: #3c3c3c !important;
|
background: #3c3c3c !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,4 +362,17 @@ ul {
|
||||||
.bigPlayer {
|
.bigPlayer {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 42px;
|
top: 42px;
|
||||||
|
box-shadow: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
#audio_upload {
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#wallAttachmentMenu {
|
||||||
|
box-shadow: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
#backdropEditor {
|
||||||
|
border: unset;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue