Открыть боковую панель
dcc0
OpenChatPhp
Коммиты
d0740544
Коммит
d0740544
создал
Янв 29, 2022
по автору
lopar
Просмотр файлов
Code clean
владелец
7fbe2178
Изменения
8
Скрыть пробелы
Построчно
Рядом
chat/html/div_updatebox.html
Просмотр файла @
d0740544
<div
id=
"updatebox"
style=
"overflow-x: hidden; width: 80%; height: 300px; margin-left: auto;
margin-right: auto;"
>
<div
id=
"parent"
class=
"message-box-template hidden"
>
</div>
</div>
\ Нет новой строки в конце файла
<div
id=
"updatebox"
style=
"overflow-x: hidden; width: 80%; height: 300px; margin-left: auto;
margin-right: auto;"
>
<div
class=
"message-box-template hidden"
id=
"parent"
>
</div>
</div>
\ Нет новой строки в конце файла
chat/html/send_form.html
Просмотр файла @
d0740544
<div
style=
"overflow-x: hidden; width: 80%; margin-left: auto;
margin-right: auto;"
>
<form
method=
"get"
onkeypress=
"if(event.keyCode == 13) return false;"
>
имя
<br/>
<input
type=
"text"
id=
"userlogin
"
name=
"userlogin"
size=
"100%"
maxlength=
"50
"
><br/>
канал
<br/>
<input
type=
"text"
id=
"channel
"
name=
"channel"
size=
"100%"
maxlength=
"50
"
><br/>
пароль (для создания канала)
<br/>
<input
type=
"password"
id=
"pass
"
name=
"pass"
size=
"100%"
maxlength=
"50
"
><br/>
сообщение
<br/>
<input
type=
"text"
id=
"text"
name=
"text"
size=
"100%
"
onkeydown=
"checkKey(event)"
maxlength
=
"
5
00"
><br/>
<input
type=
"button"
value=
"Отправить сообщение"
onclick=
"loadDoc2()"
>
</form>
<div
style=
"overflow-x: hidden; width: 80%; margin-left: auto;
margin-right: auto;"
>
<form
method=
"get"
onkeypress=
"if(event.keyCode == 13) return false;"
>
имя
<br/>
<label
for=
"userlogin"
></label><input
id=
"userlogin"
maxlength=
"50
"
name=
"userlogin"
size=
"100%"
type=
"text
"
><br/>
канал
<br/>
<label
for=
"channel"
></label><input
id=
"channel"
maxlength=
"50
"
name=
"channel"
size=
"100%"
type=
"text
"
><br/>
пароль (для создания канала)
<br/>
<label
for=
"pass"
></label><input
id=
"pass"
maxlength=
"50
"
name=
"pass"
size=
"100%"
type=
"password
"
><br/>
сообщение
<br/>
<label
for=
"text"
></label><input
id=
"text"
maxlength=
"500"
name=
"text
"
onkeydown=
"checkKey(event)"
size
=
"
1
00
%"
type=
"text
"
><br/>
<input
onclick=
"loadDoc2()"
type=
"button"
value=
"Отправить сообщение"
>
</form>
<div
id=
"canals_list"
class=
"canals-list hidden"
>
Список каналов:
<a
id=
"channel_l"
href=
"javascript:void(0)"
onclick=
"getText_author(this)"
style=
"font-style: italic;"
></a>
</div>
</div>
<br><br><br><br><br><br>
<br><br><br><br><br><br>
<br>
<br><br>
<br>
<br><br><br><br><br><br>
<br><br>
<br>
<br>
<br>
<br><br><br><br><br><br><br><br>
<br>
<br>
<br>
<br>
<br><br><br><br><br><br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
\ Нет новой строки в конце файла
<div
class=
"canals-list hidden"
id=
"canals_list"
>
Список каналов:
<a
href=
"javascript:void(0)"
id=
"channel_l"
onclick=
"getText_author(this)"
style=
"font-style: italic;"
></a>
</div>
</div>
\ Нет новой строки в конце файла
chat/lib/js/cross_object.js
Просмотр файла @
d0740544
// Кроссбраузерное создание объекта дл запроса . Обновление чата
<
script
>
// Кроссбраузерное создание объекта дл запроса . Обновление чата
function
getXmlHttp
(){
var
xmlhttp
;
try
{
xmlhttp
=
new
ActiveXObject
(
"
Msxml2.XMLHTTP
"
);
}
catch
(
e
)
{
try
{
xmlhttp
=
new
ActiveXObject
(
"
Microsoft.XMLHTTP
"
);
}
catch
(
E
)
{
xmlhttp
=
false
;
}
}
if
(
!
xmlhttp
&&
typeof
XMLHttpRequest
!=
'
undefined
'
)
{
xmlhttp
=
new
XMLHttpRequest
();
}
return
xmlhttp
;
}
// После каждого (time) интервала функция обновляет div#updatebox
function
update
()
{
var
xmlhttp
=
getXmlHttp
()
//Проверим первоначальный ввывод. Если не определено, то номер сообщения равен 0
if
(
typeof
last_message_id
==
'
undefined
'
)
{
last_message_id
=
0
;
}
//Из какого канала, если не установлен, то в chat
var
channel
=
document
.
getElementById
(
'
channel
'
).
value
;
//Проверим равно ли значение канала значению при предыдущей загрузке
//Если канал изменился, то сбросим номер сообщения до 0
if
(
window
.
channel_for_id_1
!=
channel
)
last_message_id
=
0
;
//Запрос (с выводом только последних)
xmlhttp
.
open
(
'
GET
'
,
"
/chat/lib/view/Class_Printing.php?last_message_id=
"
+
last_message_id
+
"
&channel=
"
+
channel
,
true
);
xmlhttp
.
onreadystatechange
=
function
()
{
if
(
xmlhttp
.
readyState
==
4
)
{
if
(
xmlhttp
.
status
==
200
)
{
//Получение JSON
var
myprint
=
''
;
var
mydata
=
xmlhttp
.
responseText
;
mydata
=
JSON
.
parse
(
mydata
);
//Для клонирования и цикла
var
i
;
var
itm
;
var
cln
;
//Проверим массив/Check the array
if
(
mydata
)
{
//Номер последнего сообщения/Number of last message
window
.
last_message_id
=
mydata
[
mydata
.
length
-
1
].
id
;
//span для клонирования имени и текста сообщения
var
span_sender
;
var
span_text
;
//Для замены ссылок/картинок
var
replace_link
=
/
([^\"
=
]{2}
|^
)((
https
?
|ftp
)
:
\/\/\S
+
[^\s
.,> )
\]
;'
\"
!?
])
/
;
var
replace_images
=
/
([^\"
=
]{2}
|^
)((
http|https
)\:\/\/
.*
\.(
gif|png|jpg|bmp|tif|tiff
))
/
;
//Разрешает некоторые теги
var
replace_bold_text
=
/
([
a-z
]{1,7})(
->
)(
.*
)
/
;
//Замена цвета в ООП стиле
var
replace_font_text
=
/
(
color
)(
->
)([
a-z
]{1,7})(
->
)(
.*
)
/
;
//Частный alert
var
private_to
=
/
(
alert
)(
->
)([
a-zA-Z0-9а-яёА-Я-ё
\-\_\ ]{1,100})(
->
)(
.*
)
/
var
private_login
=
document
.
getElementById
(
'
userlogin
'
).
value
;
var
thlogin
;
var
subst
;
var
withlink
;
//Собираем то, что будет напечатано
for
(
i
=
0
;
i
<
mydata
.
length
;
i
++
)
{
//Переменная с текстом
withlink
=
mydata
[
i
].
text
;
function
getXmlHttp
()
{
let
xmlhttp
;
try
{
xmlhttp
=
new
ActiveXObject
(
"
Msxml2.XMLHTTP
"
);
}
catch
(
e
)
{
try
{
xmlhttp
=
new
ActiveXObject
(
"
Microsoft.XMLHTTP
"
);
}
catch
(
E
)
{
xmlhttp
=
false
;
}
}
if
(
!
xmlhttp
&&
typeof
XMLHttpRequest
!=
'
undefined
'
)
{
xmlhttp
=
new
XMLHttpRequest
();
}
return
xmlhttp
;
}
// После каждого (time) интервала функция обновляет div#updatebox
function
update
()
{
//Проверим первоначальный ввывод. Если не определено, то номер сообщения равен 0
let
xmlhttp
=
getXmlHttp
(),
last_message_id
;
if
(
typeof
last_message_id
==
'
undefined
'
)
{
last_message_id
=
0
;
}
//Из какого канала, если не установлен, то в chat
let
channel
=
document
.
getElementById
(
'
channel
'
).
value
;
//Проверим равно ли значение канала значению при предыдущей загрузке //Если канал изменился, то сбросим номер сообщения до 0
if
(
window
.
channel_for_id_1
!==
channel
)
last_message_id
=
0
;
//Запрос (с выводом только последних)
xmlhttp
.
open
(
'
GET
'
,
"
/chat/lib/view/Class_Printing.php?last_message_id=
"
+
last_message_id
+
"
&channel=
"
+
channel
,
true
);
xmlhttp
.
onreadystatechange
=
function
()
{
if
(
xmlhttp
.
readyState
===
4
&&
xmlhttp
.
status
===
200
)
{
//Получение JSON
let
mydata
=
xmlhttp
.
responseText
;
mydata
=
JSON
.
parse
(
mydata
);
if
(
mydata
)
{
//Номер последнего сообщения/Number of last message
window
.
last_message_id
=
mydata
[
mydata
.
length
-
1
].
id
;
//Для замены ссылок/картинок
const
replace_link
=
/
([^
"=
]{2}
|^
)((
https
?
|ftp
)
:
\/\/\S
+
[^\s
.,>)
\]
;'"!?
])
/
;
const
replace_images
=
/
([^
"=
]{2}
|^
)((
http|https
)
:
\/\/
.*
\.(
gif|png|jpg|bmp|tif|tiff
))
/
;
//Разрешает некоторые теги
if
(
mydata
[
i
].
text
.
search
(
replace_bold_text
)
==
'
0
'
){
subst
=
'
<$1>$1$2$3</$1>
'
;
withlink
=
mydata
[
i
].
text
.
replace
(
replace_bold_text
,
subst
);
}
//Замена цвета
if
(
mydata
[
i
].
text
.
search
(
replace_font_text
)
==
'
0
'
){
subst
=
'
<font color=$3>$1$2$3$4$5</font>
'
;
withlink
=
mydata
[
i
].
text
.
replace
(
replace_font_text
,
subst
);
}
//Cообщения через alert
//Если для пользователя
if
(
mydata
[
i
].
text
.
search
(
private_to
)
==
'
0
'
){
thlogin
=
mydata
[
i
].
text
.
replace
(
private_to
,
'
$3
'
);
//Если логин совпал с адресатом
if
(
thlogin
==
private_login
)
{
alert
(
'
Сообщения для
'
+
private_login
);
alert
(
mydata
[
i
].
text
.
replace
(
private_to
,
'
$5
'
));
private_to
=
'
1
'
;
withlink
=
'
0
'
;
}
else
{
//Сотрем, чтобы не показывать другим
withlink
=
'
0
'
;
//Замена цвета в ООП стиле
//Частный alert
let
replace_bold_text
=
/
([
a-z
]{1,7})(
->
)(
.*
)
/
,
replace_font_text
=
/
(
color
)(
->
)([
a-z
]{1,7})(
->
)(
.*
)
/
,
private_to
=
/
(
alert
)(
->
)([
a-zA-Z0-9А-яё-
\-
_
]{1,100})(
->
)(
.*
)
/
,
private_login
=
document
.
getElementById
(
'
userlogin
'
).
value
,
thlogin
,
subst
,
withlink
;
//Собираем то, что будет напечатано
for
(
//Для клонирования и цикла
let
i
=
0
;
i
<
mydata
.
length
;
i
++
)
{
//Переменная с текстом
withlink
=
mydata
[
i
].
text
;
//Разрешает некоторые теги
if
(
mydata
[
i
].
text
.
search
(
replace_bold_text
)
===
'
0
'
)
{
subst
=
'
<$1>$1$2$3</$1>
'
;
withlink
=
mydata
[
i
].
text
.
replace
(
replace_bold_text
,
subst
);
}
//Замена цвета
if
(
mydata
[
i
].
text
.
search
(
replace_font_text
)
===
'
0
'
)
{
subst
=
'
<span style="color: $3">$1$2$3$4$5</span>
'
;
withlink
=
mydata
[
i
].
text
.
replace
(
replace_font_text
,
subst
);
}
//Cообщения через alert
//Если для пользователя
if
(
mydata
[
i
].
text
.
search
(
private_to
)
===
'
0
'
)
{
thlogin
=
mydata
[
i
].
text
.
replace
(
private_to
,
'
$3
'
);
//Если логин совпал с адресатом
if
(
thlogin
===
private_login
)
{
alert
(
'
Сообщения для
'
+
private_login
);
alert
(
mydata
[
i
].
text
.
replace
(
private_to
,
'
$5
'
));
private_to
=
'
1
'
;
withlink
=
'
0
'
;
}
else
{
//Сотрем, чтобы не показывать другим
withlink
=
'
0
'
;
}
}
//Показываем картинки
if
(
mydata
[
i
].
text
.
search
(
replace_images
)
===
'
0
'
)
{
subst
=
'
<a href="$2"><img src="$2" width="30%" alt=""></a>
'
;
withlink
=
mydata
[
i
].
text
.
replace
(
replace_images
,
subst
);
}
//Показываем Ссылки
if
(
mydata
[
i
].
text
.
search
(
replace_link
)
===
'
0
'
&&
mydata
[
i
].
text
.
search
(
replace_images
)
!==
'
0
'
)
{
subst
=
'
<a href="$2" target="_blank">$2</a>
'
;
withlink
=
mydata
[
i
].
text
.
replace
(
replace_link
,
subst
);
}
if
(
withlink
!==
'
0
'
)
{
//clone = itm.cloneNode(true); //Клонируем
let
itm
=
document
.
getElementById
(
"
parent
"
);
//Получаем id div-a
//span для клонирования имени и текста сообщения
let
span_sender
=
document
.
createElement
(
"
span
"
);
//Создадим span для отправителя
span_sender
.
setAttribute
(
"
class
"
,
"
sender
"
);
//Установим ему атрибут class для смены стиля
let
span_text
=
document
.
createElement
(
"
span
"
);
//Создадим span для текста
span_sender
.
innerHTML
=
mydata
[
i
].
login
+
'
- >
'
;
//Добавим в sender имя
span_text
.
innerHTML
=
withlink
+
'
<br/>
'
;
//Добавим текст и перенос строки
itm
.
appendChild
(
span_sender
);
//Добавим span_sender к div
itm
.
appendChild
(
span_text
);
//Добавим text к div
}
}
//Прижать scroll
document
.
getElementById
(
'
updatebox
'
).
scrollTop
=
9999999
;
window
.
channel_for_id_1
=
channel
;
}
}
//Показываем картинки
if
(
mydata
[
i
].
text
.
search
(
replace_images
)
==
'
0
'
){
subst
=
'
<a href="$2"><img src="$2" width="30%"></a>
'
;
withlink
=
mydata
[
i
].
text
.
replace
(
replace_images
,
subst
);
}
//Показываем Ссылки
if
(
mydata
[
i
].
text
.
search
(
replace_link
)
==
'
0
'
&&
mydata
[
i
].
text
.
search
(
replace_images
)
!=
'
0
'
){
subst
=
'
<a href="$2" target="_blank">$2</a>
'
;
withlink
=
mydata
[
i
].
text
.
replace
(
replace_link
,
subst
);
}
if
(
withlink
!=
'
0
'
)
{
//clone = itm.cloneNode(true); //Клонируем
itm
=
document
.
getElementById
(
"
parent
"
);
//Получаем id div-a
span_sender
=
document
.
createElement
(
"
span
"
);
//Создадим span для отправителя
span_sender
.
setAttribute
(
"
class
"
,
"
sender
"
);
//Установим ему атрибут class для смены стиля
span_text
=
document
.
createElement
(
"
span
"
);
//Создадим span для текста
span_sender
.
innerHTML
=
mydata
[
i
].
login
+
'
- >
'
;
//Добавим в sender имя
span_text
.
innerHTML
=
withlink
+
'
<br/>
'
;
//Добавим текст и перенос строки
itm
.
appendChild
(
span_sender
);
//Добавим span_sender к div
itm
.
appendChild
(
span_text
);
//Добавим text к div
}
}
//Прижать scroll
document
.
getElementById
(
'
updatebox
'
).
scrollTop
=
9999999
;
window
.
channel_for_id_1
=
channel
;
}
}
}
};
};
xmlhttp
.
send
(
null
);
}
//Каждые 30 минут обновим окно
window
.
setInterval
(
'
refresh()
'
,
1800000000
);
// Call a function every 1800000000 milliseconds (OR 30 mins).
}
// Refresh or reload page.
function
refresh
()
{
window
.
location
.
reload
();
}
//Каждые 30 минут обновим окно
window
.
setInterval
(
'
refresh()
'
,
1800000000
);
// Call a function every 1800000000 milliseconds (OR 30 mins).
// Таймер
var
time
=
3000
;
setInterval
(
"
update()
"
,
time
);
// Refresh or reload page.
function
refresh
()
{
window
.
location
.
reload
();
}
<
/script
>
// Таймер
let
time
=
3000
;
setInterval
(
"
update()
"
,
time
);
\ Нет новой строки в конце файла
chat/lib/js/list_of_channels.js
Просмотр файла @
d0740544
<
script
type
=
"
text/javascript
"
>
function
getText_author
(
str
)
{
document
.
getElementById
(
'
channel
'
).
value
=
str
.
firstChild
.
data
;
function
getText_author
(
str
)
{
document
.
getElementById
(
'
channel
'
).
value
=
str
.
firstChild
.
data
;
}
var
DATA
;
function
getFile
(
fileName
)
{
var
request
=
new
XMLHttpRequest
();
function
getFile
(
fileName
)
{
let
request
=
new
XMLHttpRequest
();
request
.
open
(
'
GET
'
,
fileName
);
request
.
onloadend
=
function
()
{
request
.
onloadend
=
function
()
{
parse
(
request
.
responseText
);
}
request
.
send
();
}
...
...
@@ -27,25 +15,18 @@ getFile('/chat/lib/view/json_list_of_channels.php'); //путь к файлу
function
parse
(
obj
)
{
var
i
,
new_item
,
clone_new_href
,
span_tilda
;
var
canals_lis
;
DATA
=
JSON
.
parse
(
obj
);
for
(
i
=
0
;
i
<
DATA
.
length
;
i
++
)
{
let
DATA
=
JSON
.
parse
(
obj
);
for
(
let
i
=
0
;
i
<
DATA
.
length
;
i
++
)
{
//Клонирование стиля и ссылки для канала
canals_lis
=
document
.
getElementById
(
"
canals_list
"
);
//получаем div
new_item
=
document
.
getElementById
(
"
channel_l
"
);
//получем каркас ссылки
clone_new_href
=
new_item
.
cloneNode
(
true
);
//клонируем каркас ссылки
let
canals_lis
=
document
.
getElementById
(
"
canals_list
"
);
//получаем div
let
new_item
=
document
.
getElementById
(
"
channel_l
"
);
//получем каркас ссылки
let
clone_new_href
=
new_item
.
cloneNode
(
true
);
//клонируем каркас ссылки
clone_new_href
.
innerHTML
=
DATA
[
i
];
//вставляем данные в каркас ссылки
canals_lis
.
appendChild
(
clone_new_href
);
//Добавим к div
span_tilda
=
document
.
createElement
(
"
span
"
);
//Добавим тильда
span_tilda
.
innerHTML
=
'
~
'
;
let
span_tilda
=
document
.
createElement
(
"
span
"
);
//Добавим тильда
span_tilda
.
innerHTML
=
'
~
'
;
canals_lis
.
appendChild
(
span_tilda
);
}
}
<
/script
>
}
\ Нет новой строки в конце файла
chat/lib/js/scroll_to_bottom.js
Просмотр файла @
d0740544
<
script
type
=
"
text/javascript
"
>
window
.
onload
=
function
(){
document
.
getElementById
(
'
updatebox
'
).
scrollTop
=
9999999
;
}
<
/script
>
window
.
onload
=
function
()
{
document
.
getElementById
(
'
updatebox
'
).
scrollTop
=
9999999
;
}
\ Нет новой строки в конце файла
chat/lib/js/send.js
Просмотр файла @
d0740544
<
script
>
//Отправка сообщения по нажатию Enter
function
loadDoc2
()
{
// Считываем значение текста, имени, канала, пароля
let
xhttp
=
new
XMLHttpRequest
(),
param
=
document
.
getElementById
(
"
text
"
).
value
,
param2
=
document
.
getElementById
(
"
userlogin
"
).
value
,
param3
=
document
.
getElementById
(
"
channel
"
).
value
,
param4
=
document
.
getElementById
(
"
pass
"
).
value
;
//Отправка сообщения по нажатию Enter
function
loadDoc2
()
{
xhttp
.
open
(
'
GET
'
,
"
./lib/Class_Send_Messages.php?text=
"
+
encodeURIComponent
(
param
)
+
"
&userlogin=
"
+
encodeURIComponent
(
param2
)
+
"
&channel=
"
+
encodeURIComponent
(
param3
)
+
"
&pass=
"
+
encodeURIComponent
(
param4
),
true
);
xhttp
.
send
();
document
.
getElementById
(
'
text
'
).
value
=
""
;
var
xhttp
=
new
XMLHttpRequest
();
var
param
=
document
.
getElementById
(
"
text
"
).
value
;
// Считываем значение текста
var
param2
=
document
.
getElementById
(
"
userlogin
"
).
value
;
// Считываем значение имени
var
param3
=
document
.
getElementById
(
"
channel
"
).
value
;
// Считываем значение канала
var
param4
=
document
.
getElementById
(
"
pass
"
).
value
;
// Считываем значение канала
xhttp
.
open
(
'
GET
'
,
"
./lib/Class_Send_Messages.php?text=
"
+
encodeURIComponent
(
param
)
+
"
&userlogin=
"
+
encodeURIComponent
(
param2
)
+
"
&channel=
"
+
encodeURIComponent
(
param3
)
+
"
&pass=
"
+
encodeURIComponent
(
param4
),
true
);
xhttp
.
send
();
document
.
getElementById
(
'
text
'
).
value
=
""
;
//scroll прижать-таки
document
.
getElementById
(
'
updatebox
'
).
scrollTop
=
9999999
;
}
function
checkKey
(
e
)
{
var
inp
=
document
.
getElementById
(
'
text
'
);
var
inp2
=
document
.
getElementById
(
'
userlogin
'
);
if
(
e
.
keyCode
==
"
13
"
)
{
loadDoc2
();
}
}
<
/script
>
//scroll прижать-таки
document
.
getElementById
(
'
updatebox
'
).
scrollTop
=
9999999
;
}
function
checkKey
(
e
)
{
var
inp
=
document
.
getElementById
(
'
text
'
),
inp2
=
document
.
getElementById
(
'
userlogin
'
);
if
(
e
.
keyCode
===
"
13
"
)
{
loadDoc2
();
}
}
\ Нет новой строки в конце файла
chat/lib/view/Class_ListChannels.php
Просмотр файла @
d0740544
<?php
//Конфиг
require_once
__DIR__
.
'/../../conf/Class_Database.php'
;
//Показать список каналов
...
...
chat/linker/linker.php
Просмотр файла @
d0740544
...
...
@@ -3,23 +3,23 @@
require_once
'close_page.php'
;
require_once
STYLE
.
'header.html'
;
//Окно чата
require_once
HTML
.
'div_updatebox.html'
;
//Форма отправки BACKENED
require_once
HTML
.
'send_form.html'
;
echo
'<script>'
;
//Показать список каналов JS FRONTED
require_once
(
LIBJS
.
'list_of_channels.js'
);
//Скролл вниз FRONTEED
require_once
LIBJS
.
'scroll_to_bottom.js'
;
//Окно чата
require_once
HTML
.
'div_updatebox.html'
;
//Файл с сообщениями чата, 15 сообщ. каждые 3 сек
require_once
LIBJS
.
'cross_object.js'
;
//Форма отправки BACKENED
require_once
HTML
.
'send_form.html'
;
//Отправка FRONTED
require_once
LIBJS
.
'send.js'
;
echo
'</script>'
;
//Удаление BACKENED
require_once
LIB
.
'Class_Count_Delete_Messages.php'
;
require_once
STYLE
.
'footer.html'
;
\ Нет новой строки в конце файла
require_once
STYLE
.
'footer.html'
;
Редактирование
Предварительный просмотр
Поддерживает Markdown
0%
Попробовать снова
или
прикрепить новый файл
.
Отмена
You are about to add
0
people
to the discussion. Proceed with caution.
Сначала завершите редактирование этого сообщения!
Отмена
Пожалуйста,
зарегистрируйтесь
или
войдите
чтобы прокомментировать