Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
Andreas Grupp
python-bigbluebutton2
Commits
65bf439f
Verified
Commit
65bf439f
authored
May 17, 2020
by
Tom Teichler
🍻
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Reformat according to black and isort
parent
2f4c4779
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
59 additions
and
37 deletions
+59
-37
bigbluebutton/api/bigbluebutton.py
bigbluebutton/api/bigbluebutton.py
+9
-4
bigbluebutton/api/meeting.py
bigbluebutton/api/meeting.py
+1
-1
bigbluebutton/api/util.py
bigbluebutton/api/util.py
+5
-14
bigbluebutton/cli/__init__.py
bigbluebutton/cli/__init__.py
+16
-11
bigbluebutton/django/apps.py
bigbluebutton/django/apps.py
+1
-1
bigbluebutton/django/models.py
bigbluebutton/django/models.py
+27
-6
No files found.
bigbluebutton/api/bigbluebutton.py
View file @
65bf439f
import
concurrent.futures
import
subprocess
from
dataclasses
import
dataclass
,
field
from
hashlib
import
sha1
from
socket
import
getfqdn
from
typing
import
Any
,
Callable
,
Dict
,
Optional
,
Sequence
from
typing
import
Any
,
Dict
,
Optional
,
Sequence
from
urllib.parse
import
urlencode
from
urllib.request
import
urlopen
from
uuid
import
uuid1
import
subprocess
import
xmltodict
...
...
@@ -87,12 +87,15 @@ class BigBlueButton:
def
generate_meeting_id
(
self
)
->
str
:
return
str
(
uuid1
())
def
ssh_command
(
self
,
command
:
Sequence
[
str
],
input
:
Optional
[
str
]
=
None
)
->
subprocess
.
CompletedProcess
:
def
ssh_command
(
self
,
command
:
Sequence
[
str
],
input
:
Optional
[
str
]
=
None
)
->
subprocess
.
CompletedProcess
:
args
=
[
"ssh"
,
"%s"
%
self
.
host
]
+
list
(
command
)
res
=
subprocess
.
run
(
args
,
capture_output
=
True
,
input
=
input
,
text
=
True
)
return
res
@
dataclass
class
BigBlueButtonGroup
:
name
:
str
...
...
@@ -128,6 +131,8 @@ class BigBlueButtonGroup:
return
meetings
def
ssh_command
(
self
,
command
:
Sequence
[
str
],
input
:
Optional
[
str
]
=
None
)
->
Dict
[
str
,
subprocess
.
CompletedProcess
]:
def
ssh_command
(
self
,
command
:
Sequence
[
str
],
input
:
Optional
[
str
]
=
None
)
->
Dict
[
str
,
subprocess
.
CompletedProcess
]:
res
=
self
.
_foreach
(
"ssh_command"
,
command
,
input
)
return
res
bigbluebutton/api/meeting.py
View file @
65bf439f
...
...
@@ -2,7 +2,7 @@ from dataclasses import dataclass, field
from
typing
import
Dict
,
Optional
from
.attendee
import
Attendee
from
.util
import
camel_to_snake
,
to_field_type
,
snake_to_camel
from
.util
import
camel_to_snake
,
snake_to_camel
,
to_field_type
@
dataclass
...
...
bigbluebutton/api/util.py
View file @
65bf439f
from
typing
import
Any
,
Union
from
typing
import
Any
from
inflection
import
camelize
,
underscore
def
snake_to_camel
(
snake
:
str
)
->
str
:
""" Convert PEP-8 complicant snake case name to special lower camel
case used by BigBlueBUtton API requests.
"""Convert PEP-8 complicant snake case name to special lower camel case.
>>> snake_to_camel("test_string")
'testString'
>>> snake_to_camel("meeting_id")
'meetingID'
"""
all_caps
=
(
"Url"
,
"Pw"
,
"Id"
)
camel
=
camelize
(
snake
,
False
)
...
...
@@ -23,19 +21,16 @@ def snake_to_camel(snake: str) -> str:
def
camel_to_snake
(
camel
:
str
)
->
str
:
""" Convert camel or lower camel case name to PEP-8 compliant snake
case used in our classes.
"""Convert camel or lower camel case name to PEP-8 compliant snake case used in our classes.
>>> camel_to_snake("meetingID")
'meeting_id'
"""
return
underscore
(
camel
)
def
get_target_type
(
cls
:
type
,
attr
:
str
)
->
type
:
""" Guess the type of a field in a class by looking at its type
annotation.
"""Guess the type of a field in a class by looking at its type annotation.
It either returns the type hint itself, or the first type argument if
it is a composite (e.g. int for a typing.Union[int, float] or a
...
...
@@ -44,7 +39,6 @@ def get_target_type(cls: type, attr: str) -> type:
WARNING: This is not generic code, but tailored to the use cases in the
specific data classes in this code base.
"""
type_
=
cls
.
__annotations__
[
attr
]
if
hasattr
(
type_
,
"__args__"
):
...
...
@@ -54,10 +48,7 @@ def get_target_type(cls: type, attr: str) -> type:
def
to_field_type
(
cls
:
type
,
attr
:
str
,
value
:
str
)
->
Any
:
""" Convert a string value to a type fitting the expected type of a field
in a class by looking at its type hint.
"""
"""Convert a string value to a type fitting the type of a field by looking at its type hint."""
type_
=
get_target_type
(
cls
,
attr
)
if
type_
is
bool
:
...
...
bigbluebutton/cli/__init__.py
View file @
65bf439f
...
...
@@ -25,15 +25,14 @@ def bbb(
group
:
str
=
"default"
,
server_name
:
Optional
[
str
]
=
None
,
):
""" Command-line wrapper for the BigBlueButton API """
"""Command-line wrapper for the BigBlueButton API."""
ctx
.
ensure_object
(
dict
)
bbb_group
=
BigBlueButtonGroup
(
group
)
# Find config files from XDG if not set
if
config
is
None
:
for
xdg_path
in
[
XDG_CONFIG_HOME
]
+
XDG_CONFIG_DIRS
:
for
xdg_path
in
[
XDG_CONFIG_HOME
]
+
XDG_CONFIG_DIRS
:
candidate
=
xdg_path
.
joinpath
(
"python-bigbluebutton2"
,
"bbb-cli.toml"
)
if
candidate
.
exists
():
config
=
open
(
candidate
,
"r"
)
...
...
@@ -68,8 +67,7 @@ def meetings(ctx):
@
meetings
.
command
(
"list"
)
@
click
.
pass_context
def
meetings_list
(
ctx
):
""" List all current meetings and basic data in tabular form """
"""List all current meetings and basic data in tabular form."""
meetings
=
ctx
.
obj
[
"apis"
].
get_meetings
()
data
=
[
...
...
@@ -94,8 +92,7 @@ def meetings_list(ctx):
@
meetings
.
command
(
"attendees"
)
@
click
.
pass_context
def
meetings_attendees
(
ctx
):
""" List all attendees in all current meetings in tabular form """
"""List all attendees in all current meetings in tabular form."""
meetings
=
ctx
.
obj
[
"apis"
].
get_meetings
()
ctx
.
obj
[
"meetings"
]
=
meetings
...
...
@@ -113,8 +110,7 @@ def meeting(ctx, meeting_id: str):
@
meeting
.
command
(
"attendees"
)
@
click
.
pass_context
def
meeting_attendees
(
ctx
):
""" List all current attendees in a meeting in tabular form """
"""List all current attendees in a meeting in tabular form."""
attendees
=
{}
for
meeting_id
,
meeting
in
ctx
.
obj
[
"meetings"
].
items
():
attendees
.
update
(
meeting
.
attendees
)
...
...
@@ -133,7 +129,17 @@ def meeting_attendees(ctx):
)
for
_
,
attendee
in
attendees
.
items
()
]
headers
=
(
"Name"
,
"ID"
,
"role"
,
"Presenter"
,
"Listening"
,
"Voice"
,
"Video"
,
"Meeting"
,
"Server"
)
headers
=
(
"Name"
,
"ID"
,
"role"
,
"Presenter"
,
"Listening"
,
"Voice"
,
"Video"
,
"Meeting"
,
"Server"
,
)
print
(
tabulate
(
data
,
headers
=
headers
))
...
...
@@ -149,7 +155,6 @@ def system(ctx):
@
click
.
pass_context
def
ssh
(
ctx
,
command
:
Tuple
[
str
]):
"""Execute command via ssh on all hosts."""
# Consume stdin completely to multiplex it
stdin
=
sys
.
stdin
.
read
()
...
...
bigbluebutton/django/apps.py
View file @
65bf439f
...
...
@@ -2,4 +2,4 @@ from django.apps import AppConfig
class
BigbluebuttonConfig
(
AppConfig
):
name
=
'
bigbluebutton
'
name
=
"
bigbluebutton
"
bigbluebutton/django/models.py
View file @
65bf439f
...
...
@@ -15,7 +15,9 @@ class BigBlueButton(models.Model):
@
classmethod
def
from_api
(
cls
,
group
,
api
):
obj
,
created
=
cls
.
update_or_create
(
url
=
api
.
url
,
group
=
group
,
defaults
=
{
"name"
:
name
,
"salt"
:
salt
})
obj
,
created
=
cls
.
update_or_create
(
url
=
api
.
url
,
group
=
group
,
defaults
=
{
"name"
:
name
,
"salt"
:
salt
}
)
obj
.
save
()
obj
.
_api
=
api
...
...
@@ -28,7 +30,9 @@ class BigBlueButton(models.Model):
if
self
.
name
in
self
.
group
.
api_group
.
apis
:
self
.
_api
=
self
.
group
.
api_group
.
apis
[
"self.name"
]
else
:
self
.
_api
=
bigbluebutton
.
BigBlueButton
(
self
.
group
.
api_group
,
self
.
name
,
self
.
url
,
self
.
salt
)
self
.
_api
=
bigbluebutton
.
BigBlueButton
(
self
.
group
.
api_group
,
self
.
name
,
self
.
url
,
self
.
salt
)
return
self
.
_api
...
...
@@ -48,9 +52,13 @@ class Meeting(models.Model):
name
=
models
.
CharField
(
verbose_name
=
_
(
"Meeting name"
),
max_length
=
60
)
welcome_message
=
models
.
TextField
(
verbose_name
=
_
(
"Welcome message"
),
blank
=
True
)
moderator_message
=
models
.
TextField
(
verbose_name
=
_
(
"Welcome message for moderators"
),
blank
=
True
)
moderator_message
=
models
.
TextField
(
verbose_name
=
_
(
"Welcome message for moderators"
),
blank
=
True
)
max_participants
=
models
.
PositiveSmallIntegerField
(
verbose_name
=
_
(
"Maximum number of participants"
),
default
=
0
)
max_participants
=
models
.
PositiveSmallIntegerField
(
verbose_name
=
_
(
"Maximum number of participants"
),
default
=
0
)
api
=
models
.
ForiegnKey
(
"BigBlueButton"
,
on_delete
=
models
.
CASCADE
,
related_name
=
"meetings"
)
...
...
@@ -58,7 +66,15 @@ class Meeting(models.Model):
@
classmethod
def
from_api
(
cls
,
api
,
meeting
):
obj
,
created
=
cls
.
update_or_create
(
name
=
meeting
.
meeting_name
,
api
=
api
,
defaults
=
{
"welcome_message"
:
meeting
.
welcome_message
,
"moderator_message"
:
meeting
.
moderator_only_message
,
"max_participants"
:
meeting
.
max_participants
})
obj
,
created
=
cls
.
update_or_create
(
name
=
meeting
.
meeting_name
,
api
=
api
,
defaults
=
{
"welcome_message"
:
meeting
.
welcome_message
,
"moderator_message"
:
meeting
.
moderator_only_message
,
"max_participants"
:
meeting
.
max_participants
,
},
)
obj
.
save
()
obj
.
_meeting
=
meeting
...
...
@@ -68,5 +84,10 @@ class Meeting(models.Model):
@
property
def
meeting
(
self
):
if
self
.
_meeting
is
None
:
self
.
_meeting
=
self
.
api
.
api
.
create_meeting
(
meeting_name
=
self
.
name
,
welcome_message
=
self
.
welcome_message
,
moderator_only_message
=
self
.
moderator_message
,
max_participants
=
self
.
max_participants
)
self
.
_meeting
=
self
.
api
.
api
.
create_meeting
(
meeting_name
=
self
.
name
,
welcome_message
=
self
.
welcome_message
,
moderator_only_message
=
self
.
moderator_message
,
max_participants
=
self
.
max_participants
,
)
return
self
.
_meeting
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