Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
F
fj-livekit
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
xianyang
fj-livekit
Commits
576900f3
Commit
576900f3
authored
Dec 06, 2023
by
xianyang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
优化1.0.0
parent
eeb25f4d
Changes
7
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
270 additions
and
262 deletions
+270
-262
.gitignore
.gitignore
+2
-1
config.yaml
bin/runtime/yaml/config.yaml
+1
-1
config.py
configs/config.py
+32
-14
validaters.py
src/app/api/friends/validaters.py
+179
-184
views.py
src/app/api/friends/views.py
+40
-51
functions.py
src/libs/functions.py
+10
-3
room.py
src/modules/room.py
+6
-8
No files found.
.gitignore
View file @
576900f3
...
...
@@ -2,4 +2,5 @@
__pycache__
lienv
bin
/bin
\ No newline at end of file
/bin
friend_env
\ No newline at end of file
bin/runtime/yaml/config.yaml
View file @
576900f3
...
...
@@ -6,7 +6,7 @@ LOG_CONFIG:
-
LOG_PATH
:
os.path.join(SITE_ROOT, "bin", "runtime", "logs", )
name
:
日志路径
SQLALCHEMY_CONFIG
:
-
DATABASE_URI
:
mysql+mysqlconnector://r
ainbowchat_pro:MK44tZZy2pzwbend@122.9.167.192:4999
/rainbowchat_pro?charset=utf8
-
DATABASE_URI
:
mysql+mysqlconnector://r
oot:iBNcMcnFhJhezYJB@106.55.103.148:3398
/rainbowchat_pro?charset=utf8
name
:
sqlchemy的url
-
SQLALCHEMY_TRACK_MODIFICATIONS
:
true
name
:
开启状态
...
...
configs/config.py
View file @
576900f3
...
...
@@ -10,32 +10,49 @@ LOG_LEVEL = logging.DEBUG
LOG_STDERR
=
False
# 输出到标准错误流
SITE_ROOT
=
os
.
path
.
dirname
(
os
.
path
.
dirname
(
os
.
path
.
abspath
(
__file__
)))
LOG_PATH
=
os
.
path
.
join
(
SITE_ROOT
,
"bin"
,
"runtime"
,
"logs"
,
""
)
CONFIG_YAML
=
os
.
path
.
join
(
SITE_ROOT
,
"bin"
,
"runtime"
,
"yaml"
,
"config.yaml"
)
APPLLO_YAML
=
os
.
path
.
join
(
SITE_ROOT
,
"bin"
,
"runtime"
,
"yaml"
,
"apollo.yaml"
)
CONFIG_YAML
=
os
.
path
.
join
(
SITE_ROOT
,
"bin"
,
"runtime"
,
"yaml"
,
"config.yaml"
)
APPLLO_YAML
=
os
.
path
.
join
(
SITE_ROOT
,
"bin"
,
"runtime"
,
"yaml"
,
"apollo.yaml"
)
apollo
=
yaml
.
safe_load
(
open
(
CONFIG_YAML
,
encoding
=
'utf-8'
))
# 获取配置
SQLALCHEMY_CONFIG
=
apollo
.
get
(
"SQLALCHEMY_CONFIG"
)
SQLALCHEMY_DATABASE_URI
=
[
item
.
get
(
"DATABASE_URI"
)
for
item
in
SQLALCHEMY_CONFIG
][
0
]
SQLALCHEMY_TRACK_MODIFICATIONS
=
[
item
.
get
(
"SQLALCHEMY_TRACK_MODIFICATIONS"
)
for
item
in
SQLALCHEMY_CONFIG
][
1
]
SDK_CONFIG
=
apollo
.
get
(
"SDK_CONFIG"
)
SDK_CONFIG
=
apollo
.
get
(
"SDK_CONFIG"
)
SDK_CONFIG_APPID
=
[
item
.
get
(
"APPID"
)
for
item
in
SDK_CONFIG
][
0
]
SDK_CONFIG_APPSECRET
=
[
item
.
get
(
"APPSECRET"
)
for
item
in
SDK_CONFIG
][
1
]
SDK_CONFIG_IDENTITY
=
[
item
.
get
(
"IDENTITY"
)
for
item
in
SDK_CONFIG
][
2
]
SDK_CONFIG_NAME
=
[
item
.
get
(
"NAME"
)
for
item
in
SDK_CONFIG
][
3
]
UPLOAD_FOLDER
=
os
.
path
.
join
(
SITE_ROOT
,
"bin"
,
"runtime"
,
"files"
,
""
)
COS_FOLDER
=
os
.
path
.
join
(
SITE_ROOT
,
"bin"
,
"runtime"
,
"cos_files"
)
COS_CONFIG
=
apollo
.
get
(
"COS_CONFIG"
)
Region
=
[
item
.
get
(
"Region"
)
for
item
in
COS_CONFIG
][
0
]
SecretId
=
[
item
.
get
(
"SecretId"
)
for
item
in
COS_CONFIG
][
1
]
SecretKey
=
[
item
.
get
(
"SecretKey"
)
for
item
in
COS_CONFIG
][
2
]
Token
=
[
item
.
get
(
"Token"
)
for
item
in
COS_CONFIG
][
3
]
scheme
=
[
item
.
get
(
"Scheme"
)
for
item
in
COS_CONFIG
][
4
]
Bucket
=
[
item
.
get
(
"Bucket"
)
for
item
in
COS_CONFIG
][
5
]
UPLOAD_FOLDER
=
os
.
path
.
join
(
SITE_ROOT
,
"bin"
,
"runtime"
,
"files"
,
""
)
COS_FOLDER
=
os
.
path
.
join
(
SITE_ROOT
,
"bin"
,
"runtime"
,
"cos_files"
)
COS_CONFIG
=
apollo
.
get
(
"COS_CONFIG"
)
Region
=
[
item
.
get
(
"Region"
)
for
item
in
COS_CONFIG
][
0
]
SecretId
=
[
item
.
get
(
"SecretId"
)
for
item
in
COS_CONFIG
][
1
]
SecretKey
=
[
item
.
get
(
"SecretKey"
)
for
item
in
COS_CONFIG
][
2
]
Token
=
[
item
.
get
(
"Token"
)
for
item
in
COS_CONFIG
][
3
]
scheme
=
[
item
.
get
(
"Scheme"
)
for
item
in
COS_CONFIG
][
4
]
Bucket
=
[
item
.
get
(
"Bucket"
)
for
item
in
COS_CONFIG
][
5
]
config
=
CosConfig
(
Region
=
Region
,
SecretId
=
SecretId
,
SecretKey
=
SecretKey
,
Token
=
Token
,
Scheme
=
scheme
)
client
=
CosS3Client
(
config
)
# business BUSINESS
class
TestEnv
(
BaseSettings
):
DEBUG
:
bool
=
True
TESTING
:
bool
=
False
DATABASE_URI
:
str
=
'sqlite://:memory:'
DATABASE_USER
:
str
=
''
DATABASE_PWD
:
str
=
''
BUSINESS
:
dict
=
{
"database"
:
"rainbowchat_pro"
,
"host"
:
"106.55.103.148"
,
"port"
:
3398
,
"pwd"
:
"iBNcMcnFhJhezYJB"
,
"user"
:
"root"
}
JAVA_PATH
=
"https://chat.pro.zhubei.cn/rainbowchat_pro_test"
class
Env
(
BaseSettings
):
DEBUG
:
bool
=
True
TESTING
:
bool
=
False
...
...
@@ -49,7 +66,8 @@ class Env(BaseSettings):
"pwd"
:
"MK44tZZy2pzwbend"
,
"user"
:
"rainbowchat_pro"
}
JAVA_PATH
=
"https://chat.pro.zhubei.cn/rainbowchat_pro
_test
"
JAVA_PATH
=
"https://chat.pro.zhubei.cn/rainbowchat_pro"
env
=
Env
()
env
=
TestEnv
()
# env = Env()
src/app/api/friends/validaters.py
View file @
576900f3
This diff is collapsed.
Click to expand it.
src/app/api/friends/views.py
View file @
576900f3
#encoding=utf-8
#
encoding=utf-8
import
os
from
werkzeug.utils
import
secure_filename
...
...
@@ -18,11 +18,11 @@ from src.modules.friend import FriendMessage, FriendComment, FriendGive
def
friends_add
():
"""朋友圈发送消息 视频文件存储到我的相册"""
form
=
FriendSendAddFrom
()
.
validate_
()
fcmdata
=
save_friends
(
form
.
data
)
return
result_format
(
code
=
200
,
message
=
'发布成功'
,
id
=
fcmdata
.
id
)
fcmdata
=
save_friends
(
form
.
data
)
return
result_format
(
code
=
200
,
message
=
'发布成功'
,
id
=
fcmdata
)
@
api
.
route
(
'/circle/list'
,
methods
=
[
'GET'
])
@
api
.
route
(
'/circle/list'
,
methods
=
[
'GET'
])
def
friends_list
():
'''
朋友圈列表
...
...
@@ -30,56 +30,55 @@ def friends_list():
form
=
FriendsListFrom
(
request
.
args
)
.
validate_
()
page
=
request
.
args
.
get
(
'page'
,
default
=
1
,
type
=
int
)
limit
=
request
.
args
.
get
(
'size'
,
default
=
10
,
type
=
int
)
query_user
=
FriendMessage
.
query
.
filter
()
.
order_by
(
FriendMessage
.
id
.
desc
())
query_user
=
FriendMessage
.
query
.
filter
(
audit_status
=
2
)
.
order_by
(
FriendMessage
.
id
.
desc
())
if
form
.
params
:
query_user
=
query_user
.
filter
(
*
form
.
params
)
paginate
=
query_user
.
paginate
(
page
=
page
,
per_page
=
limit
,
error_out
=
True
)
data
=
[
item
.
serialization
(
increase
=
{
'create_time'
,
'uid'
,
'status'
})
for
item
in
paginate
.
items
]
datas
=
get_infoname
(
data
)
data
=
[
item
.
serialization
(
increase
=
{
'create_time'
,
'uid'
,
'status'
})
for
item
in
paginate
.
items
]
datas
=
get_infoname
(
data
)
items
=
paginate_info
(
paginate
=
paginate
)
return
result_format
(
code
=
200
,
data
=
datas
,
**
items
,
message
=
"查询成功"
)
@
api
.
route
(
'/circle/comment'
,
methods
=
[
'POST'
])
@
api
.
route
(
'/circle/comment'
,
methods
=
[
'POST'
])
def
friends_comment
():
'''
朋友圈评论
'''
form
=
FriendCommentAddFrom
()
.
validate_
()
fcmdata
=
save_comment
(
form
.
data
)
FriendMessageNotice
(
form
.
fcmid
.
data
,
fcmdata
,
form
.
uid
.
data
)
.
query_praise_comment
()
return
result_format
(
code
=
200
,
id
=
fcmdata
.
id
,
message
=
'评论成功'
)
fcmdata
=
save_comment
(
form
.
data
)
FriendMessageNotice
(
form
.
fcmid
.
data
,
fcmdata
,
form
.
uid
.
data
)
.
query_praise_comment
()
return
result_format
(
code
=
200
,
id
=
fcmdata
.
id
,
message
=
'评论成功'
)
@
api
.
route
(
'/circle/comment/delete'
,
methods
=
[
'GET'
])
@
api
.
route
(
'/circle/comment/delete'
,
methods
=
[
'GET'
])
def
friends_comment_delete
():
'''
删除评论
'''
FriendCommentDeleteFrom
(
request
.
args
)
.
validate_
()
return
result_format
(
code
=
200
,
message
=
'评论成功'
)
return
result_format
(
code
=
200
,
message
=
'评论成功'
)
@
api
.
route
(
'/circle/give'
,
methods
=
[
'POST'
])
@
api
.
route
(
'/circle/give'
,
methods
=
[
'POST'
])
def
friends_give
():
'''
朋友圈信息点赞
'''
form
=
FriendGivetAddFrom
()
.
validate_
()
friend_info
=
FriendGive
.
query
.
order_by
(
FriendGive
.
id
.
desc
())
.
filter
(
FriendGive
.
fcmid
==
form
.
fcmid
.
data
,
FriendGive
.
uid
==
form
.
uid
.
data
,
)
.
first
()
friend_info
=
FriendGive
.
query
.
order_by
(
FriendGive
.
id
.
desc
())
.
filter
(
FriendGive
.
fcmid
==
form
.
fcmid
.
data
,
FriendGive
.
uid
==
form
.
uid
.
data
,
)
.
first
()
if
friend_info
:
if
friend_info
.
status
==
1
:
if
friend_info
.
status
==
1
:
friend_info
.
set_attrs
({
'status'
:
0
})
.
direct_update_
()
else
:
friend_info
.
set_attrs
({
'status'
:
1
})
.
direct_update_
()
friend_info
.
set_attrs
({
'status'
:
1
})
.
direct_update_
()
FriendMessageNotice
(
form
.
fcmid
.
data
,
friend_info
,
form
.
uid
.
data
)
.
query_praise_comment
()
else
:
res_data
=
FriendGive
()
.
set_attrs
(
form
.
data
)
.
direct_commit_
()
FriendMessageNotice
(
form
.
fcmid
.
data
,
res_data
,
form
.
uid
.
data
)
.
query_praise_comment
()
return
result_format
(
code
=
200
,
message
=
'操作成功'
)
return
result_format
(
code
=
200
,
message
=
'操作成功'
)
# @api.route('/circle/give/delete',methods=['POST'])
...
...
@@ -100,28 +99,24 @@ def circle_of_friends():
return
result_format
(
code
=
200
,
data
=
res_data
,
message
=
"查询成功"
)
@
api
.
route
(
'/circle/delete'
,
methods
=
[
'POST'
])
@
api
.
route
(
'/circle/delete'
,
methods
=
[
'POST'
])
def
friends_circle_delete
():
'''
删出发文内容
'''
form
=
FriendGivetDeleteFrom
()
.
validate_
()
FriendGive
()
.
set_attrs
(
form
.
data
)
.
direct_commit_
()
return
result_format
(
code
=
200
,
message
=
'删除成功'
)
return
result_format
(
code
=
200
,
message
=
'删除成功'
)
@
api
.
route
(
'/circle/background'
,
methods
=
[
'POST'
])
def
friends_ground_edit
():
"""朋友圈背景图修改"""
FriendBackgroundFrom
()
.
validate_
()
return
result_format
(
code
=
200
,
message
=
'操作成功'
)
return
result_format
(
code
=
200
,
message
=
'操作成功'
)
@
api
.
route
(
'/trends/list'
,
methods
=
[
'GET'
])
@
api
.
route
(
'/trends/list'
,
methods
=
[
'GET'
])
def
trends_list
():
'''
动态列表
...
...
@@ -130,49 +125,45 @@ def trends_list():
limit
=
request
.
args
.
get
(
'size'
,
default
=
10
,
type
=
int
)
query_user
=
FriendMessage
.
query
.
filter
()
.
order_by
(
FriendMessage
.
id
.
desc
())
paginate
=
query_user
.
paginate
(
page
=
page
,
per_page
=
limit
,
error_out
=
True
)
data
=
[
item
.
serialization
(
increase
=
{
'create_time'
,
'uid'
,
'status'
},
)
for
item
in
paginate
.
items
]
datas
=
get_infoname
(
data
)
data
=
[
item
.
serialization
(
increase
=
{
'create_time'
,
'uid'
,
'status'
},
)
for
item
in
paginate
.
items
]
datas
=
get_infoname
(
data
)
items
=
paginate_info
(
paginate
=
paginate
)
return
result_format
(
code
=
200
,
data
=
datas
,
**
items
,
message
=
"查询成功"
)
@
api
.
route
(
'/circle/upload'
,
methods
=
[
'POST'
])
@
api
.
route
(
'/circle/upload'
,
methods
=
[
'POST'
])
def
circle_upload
():
'''
图片视频上传到oss
'''
file
=
request
.
files
[
'file'
]
# filename, suffix = file.filename.split('.') # 获取上传文件的文件名
file_strem
=
file
.
read
()
filename_path
=
upload_file
(
file_strem
,
file
.
filename
)
file_strem
=
file
.
read
()
filename_path
=
upload_file
(
file_strem
,
file
.
filename
)
return
result_format
(
code
=
200
,
data
=
filename_path
,
**
{
"message"
:
"上传成功"
})
@
api
.
route
(
'/comment/list'
,
methods
=
[
'GET'
])
@
api
.
route
(
'/comment/list'
,
methods
=
[
'GET'
])
def
circle_comment
():
'''
评论列表
'''
form
=
FriendsCommentListFrom
(
request
.
args
)
.
validate_
()
data
=
children_comment
(
form
.
fcmid
.
data
)
return
result_format
(
code
=
200
,
data
=
data
,
message
=
"查询成功"
)
data
=
children_comment
(
form
.
fcmid
.
data
,
form
.
myUid
.
data
)
return
result_format
(
code
=
200
,
data
=
data
,
message
=
"查询成功"
)
@
api
.
route
(
'/give/list'
,
methods
=
[
'GET'
])
@
api
.
route
(
'/give/list'
,
methods
=
[
'GET'
])
def
give_list
():
'''
点赞列表
'''
form
=
FriendsCommentListFrom
(
request
.
args
)
.
validate_
()
data
=
list_give
(
form
.
fcmid
.
data
,
form
.
uid
.
data
)
return
result_format
(
code
=
200
,
data
=
data
,
message
=
"查询成功"
)
data
=
list_give
(
form
.
fcmid
.
data
,
form
.
uid
.
data
)
return
result_format
(
code
=
200
,
data
=
data
,
message
=
"查询成功"
)
@
api
.
route
(
'/circle/info'
,
methods
=
[
'GET'
])
@
api
.
route
(
'/circle/info'
,
methods
=
[
'GET'
])
def
circle_info_list
():
'''
获取用户朋友圈(详情)
...
...
@@ -182,18 +173,16 @@ def circle_info_list():
form
=
CircleListFrom
(
request
.
args
)
.
validate_
()
query_user
=
FriendMessage
.
query
.
filter
(
*
form
.
params
)
.
order_by
(
FriendMessage
.
id
.
desc
())
paginate
=
query_user
.
paginate
(
page
=
page
,
per_page
=
limit
,
error_out
=
True
)
data
=
[
item
.
serialization
(
increase
=
{
'create_time'
,
'uid'
,
'status'
})
for
item
in
paginate
.
items
]
datas
=
get_infoname
(
data
)
data
=
[
item
.
serialization
(
increase
=
{
'create_time'
,
'uid'
,
'status'
})
for
item
in
paginate
.
items
]
datas
=
get_infoname
(
data
)
items
=
paginate_info
(
paginate
=
paginate
)
return
result_format
(
code
=
200
,
data
=
datas
,
**
items
,
message
=
"查询成功"
)
@
api
.
route
(
'/content/delete'
,
methods
=
[
'GET'
])
@
api
.
route
(
'/content/delete'
,
methods
=
[
'GET'
])
def
friends_delete
():
'''
删除朋友圈信息
'''
ContentListFrom
(
request
.
args
)
.
validate_
()
return
result_format
(
code
=
200
,
message
=
'删除成功'
)
\ No newline at end of file
return
result_format
(
code
=
200
,
message
=
'删除成功'
)
src/libs/functions.py
View file @
576900f3
...
...
@@ -9,6 +9,8 @@ import decimal
import
time
import
requests
from
livekit
import
AccessToken
,
VideoGrant
from
sqlalchemy
import
or_
,
and_
from
configs.config
import
SDK_CONFIG_APPSECRET
,
SDK_CONFIG_APPID
,
client
,
Bucket
,
env
,
SecretKey
,
Region
,
UPLOAD_FOLDER
from
src.libs.db_link
import
LinkMysql
from
src.libs.log_utils
import
Logger
...
...
@@ -362,12 +364,17 @@ def upload_file_body(file_strem, file_name):
return
dir_to_create
def
children_comment
(
fcmid
):
def
children_comment
(
fcmid
,
visitor_id
):
result
=
[]
fs
=
[]
friend_data
=
FriendComment
.
query
.
filter
(
FriendComment
.
fcmid
==
fcmid
)
.
all
()
friend_data
=
FriendComment
.
query
.
filter
(
or_
(
and_
(
FriendComment
.
status
==
0
,
FriendComment
.
fcmid
==
int
(
fcmid
)),
and_
(
FriendComment
.
uid
==
int
(
visitor_id
),
FriendComment
.
fcmid
==
int
(
fcmid
))))
.
all
()
for
infos
in
friend_data
:
result
.
append
(
infos
.
serialization
())
d
=
infos
.
serialization
()
d
[
'status'
]
=
infos
.
status
result
.
append
(
d
)
ds
=
sorted
(
result
,
key
=
lambda
x
:
x
[
'review_to'
]
if
x
[
'review_to'
]
else
0
,
reverse
=
True
)
datas
=
one_tree_comment
(
ds
,
fs
)
return
datas
...
...
src/modules/room.py
View file @
576900f3
...
...
@@ -8,22 +8,20 @@ from src.app.orm import Common, db
class
Room
(
Common
,
db
.
Model
):
"""房间的基本信息"""
__tablename__
=
'room'
id
=
db
.
Column
(
db
.
Integer
,
primary_key
=
True
,
autoincrement
=
True
)
id
=
db
.
Column
(
db
.
Integer
,
primary_key
=
True
,
autoincrement
=
True
)
name
=
db
.
Column
(
db
.
String
(
255
),
comment
=
"房间名字"
)
empty_timeout
=
db
.
Column
(
db
.
Integer
,
comment
=
"过期时间(秒)"
)
max_participants
=
db
.
Column
(
db
.
Integer
,
comment
=
"限制房间内的参与者人数"
)
metadatas
=
db
.
Column
(
db
.
String
(
500
),
comment
=
"原数据存储"
)
create_user
=
db
.
Column
(
db
.
String
(
100
),
comment
=
"创建者"
)
create_time
=
db
.
Column
(
TIMESTAMP
,
default
=
datetime
.
datetime
.
now
(),
comment
=
"创建者"
)
node_id
=
db
.
Column
(
db
.
String
(
320
),
comment
=
"节点编号"
)
create_user
=
db
.
Column
(
db
.
String
(
100
),
comment
=
"创建者"
)
create_time
=
db
.
Column
(
TIMESTAMP
,
default
=
datetime
.
datetime
.
now
(),
comment
=
"创建者"
)
node_id
=
db
.
Column
(
db
.
String
(
320
),
comment
=
"节点编号"
)
class
RoomLogo
(
Common
,
db
.
Model
):
"""请求日志拦截"""
__tablename__
=
'room_log'
id
=
db
.
Column
(
db
.
Integer
,
primary_key
=
True
,
autoincrement
=
True
)
id
=
db
.
Column
(
db
.
Integer
,
primary_key
=
True
,
autoincrement
=
True
)
username
=
db
.
Column
(
db
.
String
(
11
),
comment
=
"用户名"
)
login_ip
=
db
.
Column
(
db
.
String
(
50
),
comment
=
"登录ip"
)
create_by
=
db
.
Column
(
db
.
String
(
64
),
comment
=
"创建者"
)
...
...
@@ -31,4 +29,4 @@ class RoomLogo(Common, db.Model):
remark
=
db
.
Column
(
db
.
Text
,
comment
=
"备注"
)
password_hash
=
db
.
Column
(
db
.
String
(
150
))
stop
=
Column
(
SMALLINT
,
default
=
0
,
comment
=
'当前账号默认情况,0为正常,1为停用'
)
label
=
Column
(
db
.
Integer
,
default
=
1
,
comment
=
"标签0为administrator,1为none无权限,2为work权限有任务管理和日志管理。3为supervisor的日志管理"
)
\ No newline at end of file
label
=
Column
(
db
.
Integer
,
default
=
1
,
comment
=
"标签0为administrator,1为none无权限,2为work权限有任务管理和日志管理。3为supervisor的日志管理"
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment