def join_room(): """View to let user join a virtual room""" form = RoomForm() # if the form is submitted and valid if form.validate_on_submit(): roomId = form.roomId.data.strip() password = form.password.data username = form.username.data.strip().replace(" ", "_") b = BigBlueButton(BBB_SERVER_URL, BBB_SERVER_SECRET) r = b.is_meeting_running(roomId) active_room = json.loads(r['xml']['running'].lower()) # check if the meeting exists if not active_room: return render_template('conference/join_conference.html', form=form, existingId=True) else: # get room url room_url = b.get_join_meeting_url(username, roomId, password) # redirect to the room return redirect(room_url) return render_template('conference/join_conference.html', form=form)
async def execute_request(): b = BigBlueButton(server.url, server.secret) try: b.get_meeting_info(meeting_id) except Exception: await asyncio.sleep(0.01) return False await asyncio.sleep(0.01) return True
def create_room(): """View to let user create a virtual room""" if current_user.is_authenticated: if ('admin' in current_user.roles) | ('roomCreator' in current_user.roles): form = RoomForm() # if the form is submitted and valid if form.validate_on_submit(): roomId = form.roomId.data.strip() password = form.password.data username = form.username.data.strip().replace(" ", "_") modPassword = secrets.token_urlsafe(64) b = BigBlueButton(BBB_SERVER_URL, BBB_SERVER_SECRET) # params dict = { 'name': username, 'attendeePW': password, 'moderatorPW': modPassword, 'record': True } if os.getenv('CURRENT_HOST'): dict['logoutURL'] = os.getenv('CURRENT_HOST') try: # use create meeting b.create_meeting(roomId, params=dict) except BBBException: return render_template('conference/create_conference.html', form=form, existingId=True) # get room url room_url = b.get_join_meeting_url(username, roomId, modPassword) # redirect to the created room return redirect(room_url) return render_template('conference/create_conference.html', form=form) else: return render_template('conference/info_create.html') else: return render_template('conference/info_create.html')
def init_bbb(self, server): servers = {} res = self.r.get("server:{}".format(server)) if res: servers[server] = json.loads(res) BBB_URL = servers[server]['BBB_URL'] BBB_SECRET = servers[server]['BBB_SECRET'] self.bbb = BigBlueButton(BBB_URL, BBB_SECRET) self.bbbUrl = bbbUtil.UrlBuilder(BBB_URL, BBB_SECRET) self.logger.debug("connected to bbb server: {}".format(server)) return True else: self.logger.error( "could not connect to bbb server: {}".format(server)) return False
def post(self, request, cid="", *args, **kwargs): try: campaign = CampaignModel.objects.get(id=cid) except CampaignModel.DoesNotExist: return Http404 try: account = AccountModel.objects.get(user__username=request.user) except AccountModel.DoesNotExist: return Http404 bbb = BigBlueButton(settings.BBB_HOST, settings.BBB_SECRET) # TODO: INSECURE AS SHIT attendee = hashlib.md5( (campaign.name + "mod").encode("utf-8")).hexdigest().replace( "&", "-") moderator = hashlib.md5( (campaign.name + "att").encode("utf-8")).hexdigest().replace( "&", "-") meeting_id = hashlib.md5( campaign.name.encode("utf-8")).hexdigest().replace("&", "-") try: bbb.create_meeting(meeting_id, params={ "attendeePW": attendee, "moderatorPW": moderator }) except Exception: pass is_moderator = request.user.id in [ x.user.id for x in campaign.game_master.all() ] or request.user.is_superuser url = bbb.get_join_meeting_url(request.POST["name"], meeting_id, moderator if is_moderator else attendee) return redirect(url)
class RoomUtil: logging.basicConfig(level=logging.DEBUG) def __init__(self, bbbUrl, bbbSecret): logging.info("setup BBB connection") self.bbb = BigBlueButton(bbbUrl, bbbSecret) def __existRoom(self, roomId): try: self.bbb.get_meeting_info(roomId) return True except: return False def getRoomUrl(self, roomId, username="******".format(str(uuid.uuid4())), moderator=False): logging.info("getRoomUrl with roomId: {}".format(roomId)) if not self.__existRoom(roomId): attendeePW = str(uuid.uuid4()) moderatorPW = str(uuid.uuid4()) dict = {'attendeePW': attendeePW, 'moderatorPW': moderatorPW} self.bbb.create_meeting(roomId, params=dict) else: meetingInfo = self.bbb.get_meeting_info(roomId).get_meetinginfo() attendeePW = meetingInfo.get_attendeepw() moderatorPW = meetingInfo.get_moderatorpw() if (moderator): userPw = moderatorPW else: userPw = attendeePW meetingInfoJson = self.bbb.get_meeting_info(meeting_id=roomId) logging.debug(json.dumps(meetingInfoJson, indent=1)) return self.bbb.get_join_meeting_url(username, roomId, userPw)
help="attendee password (required to create meetings)") parser.add_argument("-M", "--moderatorPassword", help="moderator password (required to create a meeting)") parser.add_argument("-T", "--meetingTitle", help="meeting title (required to create a meeting)") parser.add_argument("-u", "--user", help="Name to join the meeting", default="Live") parser.add_argument("-t", "--target", help="RTMP Streaming URL") parser.add_argument("-c", "--chat", help="Show the chat", action="store_true") args = parser.parse_args() bbb = BigBlueButton(args.server, args.secret) def set_up(): global browser options = Options() options.add_argument('--disable-infobars') options.add_argument('--no-sandbox') options.add_argument('--kiosk') options.add_argument('--window-size=1920,1080') options.add_argument('--window-position=0,0') options.add_experimental_option("excludeSwitches", ['enable-automation']) options.add_argument('--shm-size=1gb') options.add_argument('--disable-dev-shm-usage') options.add_argument('--start-fullscreen')
def get_instance(self): return BigBlueButton(self.url, self.api_key)
def find_meeting(server, title): meetings = get_meetings(server) for meeting in meetings: if title in meeting['meetingName']: meeting['joinAttendeeUrl'] = get_join_url(meeting['meetingID'], args.user, 'attendee') meeting['joinModeratorUrl'] = get_join_url(meeting['meetingID'], args.user, 'moderator') return meeting def show_meetings(server): meetings = get_meetings(server) for meeting in meetings: print(meeting['meetingName']) print("ID: {}".format(meeting['meetingID'])) print("ATTENDEE_PASSWORD: {}".format(meeting['attendeePW'])) joinAttendeeUrl = get_join_url(meeting['meetingID'], args.user, 'attendee') print("JOIN_ATTENDEE_URL: {}".format(joinAttendeeUrl)) print("MODERATOR_PASSWORD: {}".format(meeting['moderatorPW'])) joinModeratorUrl = get_join_url(meeting['meetingID'], args.user, 'moderator') print("JOIN_MODERATOR_URL: {}".format(joinModeratorUrl)) print("") bbb = BigBlueButton(args.server, args.secret) show_meetings(args.server)
from django.conf import settings from api.models import Chat from bigbluebutton_api_python import BigBlueButton bbb_api = BigBlueButton(settings.BBB_URL, settings.BBB_SECRET) class State: """ A cache for the Chat model, to decrease db load """ instance = None def __init__(self): self.internal = {} """Mapping from internal meeting id to chat object""" self.external = {} """Mapping from external meeting id to chat object""" for chat in Chat.objects.all(): self._add(chat) def _add(self, chat): self.external[chat.external_meeting_id] = chat self.internal[chat.internal_meeting_id] = chat
class scheduLight: """ core functions for processing of commands and meetings """ # set startTime NOW = datetime.now() # prepare bbb bbb = None bbbUrl = None # keep status entris for n seconds keep_redis_cache = "31536000" # write to this logFile logFile = 'scheduLight.log' # define schemas meeting_schema = dataSchema.meetingSchema() server_schema = dataSchema.serverSchema() command_schema = dataSchema.commandSchema() command_rename_room_schema = dataSchema.commandRenameRoomSchema command_share_room_schema = dataSchema.commandShareRoomSchema command_create_room_schema = dataSchema.commandCreateRoomSchema command_create_user_schema = dataSchema.commandCreateUserSchema validate_schema = dataSchema.validate_schema def __init__(self, args={}): if 'keep_redis_cache' in args: self.keep_redis_cache = args.keep_redis_cache if 'logFile' in args: self.logFile = args.logFile ## create logger with 'scheduLight' self.logger = logging.getLogger('scheduLight') self.logger.setLevel(logging.DEBUG) ## create file handler which logs even debug messages fh = logging.handlers.RotatingFileHandler(self.logFile, maxBytes=1000000, backupCount=5) fh.setLevel(logging.DEBUG) ## create console handler with a higher log level ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) ## create formatter and add it to the handlers formatter = logging.Formatter( '%(asctime)s %(name)-12s %(levelname)-8s %(message)s', '%Y-%m-%d %H:%M:%S') fh.setFormatter(formatter) formatter2 = logging.Formatter('%(levelname)-8s %(message)s') ch.setFormatter(formatter2) ## add the handlers to the logger self.logger.addHandler(fh) self.logger.addHandler(ch) # # connect to redis db self.r = redis.StrictRedis(host="localhost", port="6380", db=1, ssl=False, charset="utf-8", decode_responses=True) try: self.r.info() except redis.exceptions.ConnectionError as ERR: self.logger.error("Redis not ready: {}".format(ERR)) sys.exit() # prepare mail queue try: #self.r.xgroup_destroy('mailStream', 'mailNotifications') self.r.xgroup_create('mailStream', 'mailNotifications', '0-0', True) except Exception as ERR: self.logger.debug("Redis stream warning: {}".format(ERR)) #prepare command queue try: #self.r.xgroup_destroy('commandStream', 'commandNotifications') self.r.xgroup_create('commandStream', 'commandNotifications', '0-0', True) except Exception as ERR: self.logger.debug("Redis stream warning: {}".format(ERR)) def init_bbb(self, server): servers = {} res = self.r.get("server:{}".format(server)) if res: servers[server] = json.loads(res) BBB_URL = servers[server]['BBB_URL'] BBB_SECRET = servers[server]['BBB_SECRET'] self.bbb = BigBlueButton(BBB_URL, BBB_SECRET) self.bbbUrl = bbbUtil.UrlBuilder(BBB_URL, BBB_SECRET) self.logger.debug("connected to bbb server: {}".format(server)) return True else: self.logger.error( "could not connect to bbb server: {}".format(server)) return False def get_date(self, dateString): format_string = "%Y-%m-%d %H:%M" return datetime.strptime(dateString, format_string) def render_template(self, template, **kwargs): template_file = os.path.dirname(__file__) + '/templates/' + template if not os.path.exists(template_file): self.logger.error( "Mail Template {} not found!".format(template_file)) sys.exit() templateLoader = jinja2.FileSystemLoader( searchpath=os.path.dirname(__file__) + '/templates/') templateEnv = jinja2.Environment(loader=templateLoader) templ = templateEnv.get_template(template) return templ.render(**kwargs) def config_exists(self, my_dict, my_list): for my_item in my_list: if my_item not in my_dict: return False return True def random_secret(self, stringLength=11): lettersAndDigits = string.ascii_letters + string.digits return ''.join( (random.choice(lettersAndDigits) for i in range(stringLength))) def get_status(self, base, path, displayType='returnCode', type='meeting'): search_base = "{}:{}:status".format(type, base) search_path = str.join("_", path) statusList = self.r.hget(search_base, search_path) if statusList == None: self.logger.debug("no status found for {} {}".format( base, search_path)) return None statusList = json.loads(statusList) if not isinstance(statusList, list): self.logger.debug("corrupted status found for {}".format(base)) return None self.r.touch(search_base) # return status if displayType == 'raw': return statusList (date, returnCode, message) = statusList[-1].split("|") self.logger.debug("status: {} {} {} ({})".format( returnCode, message, date, search_path)) if displayType == 'date': return date elif displayType == 'returnCode': return returnCode else: return message def set_status(self, base, path, returnCode, message, type='meeting'): search_base = "{}:{}:status".format(type, base) search_path = str.join("_", path) oldStatus = self.get_status(base, path, 'raw', type) if oldStatus != None and oldStatus[-1].split('|')[1] == returnCode: self.logger.debug("status already set to {} {}".format( returnCode, message)) return None else: if not isinstance(oldStatus, list): oldStatus = [] oldStatus.append("{}|{}|{}".format(self.NOW, returnCode, message)) self.r.hset(search_base, search_path, json.dumps(oldStatus)) self.r.expire(search_base, self.keep_redis_cache) self.logger.debug("set status: {} {} ({})".format( returnCode, message, search_path)) return True def meeting_info(self, bbb_id): try: minfo = self.bbb.get_meeting_info(bbb_id) except bbbexception.BBBException as ERR: return 0 return minfo def end_meeting(self, bbb_id): try: minfo = self.bbb.get_meeting_info(bbb_id) except bbbexception.BBBException as ERR: return 0 moderator_pw = minfo.get_meetinginfo().get_moderatorpw() try: meetingsXML = self.bbb.end_meeting(bbb_id, moderator_pw) except bbbexception.BBBException as ERR: return 0 if meetingsXML.get_field('returncode') == 'SUCCESS': if meetingsXML.get_field('messageKey') == 'sentEndMeetingRequest': self.logger.debug("meeting {}: {}".format( meetingName, meetingsXML.get_field('message'))) return 1 return 0 def start_meeting(self, bbb_id, meetingTitle=None, moderatorPassword=None, attendeePassword=None, muteOnStart=None, welcome=None, bannerText=None, maxParticipants=None, logoutURL=None, record=None, duration=None, autoStartRecording=None, allowStartStopRecording=None): create_params = {} if moderatorPassword: create_params['moderatorPW'] = moderatorPassword if attendeePassword: create_params['attendeePW'] = attendeePassword if muteOnStart: create_params['muteOnStart'] = muteOnStart if welcome: create_params['welcome'] = welcome if bannerText: create_params['bannerText'] = bannerText if maxParticipants: create_params['maxParticipants'] = maxParticipants if logoutURL: create_params['logoutURL'] = "https://{}".format(logoutURL) if record: create_params['record'] = record if duration: create_params['duration'] = duration if autoStartRecording: create_params['autoStartRecording'] = autoStartRecording if allowStartStopRecording: create_params['allowStartStopRecording'] = allowStartStopRecording if meetingTitle: create_params['name'] = meetingTitle try: meetingsXML = self.bbb.create_meeting(bbb_id, params=create_params) except bbbexception.BBBException as ERR: self.logger.error(ERR) return 0 if meetingsXML.get_field('returncode') == 'SUCCESS': if meetingsXML.get_field('messageKey') == 'duplicateWarning': self.logger.debug("meeting already running: {}".format( meetingsXML.get_field('message'))) if meetingsXML.get_field('hasUserJoined') == 'false': self.logger.debug("no users have joined yet, keeping open") # keep open return 2 # users have joined - stop processing self.logger.debug("users have joined stopping to process") return 1 # failed to start meeting self.logger.debug("failed to start meeting") return 0 def get_join_url(self, id, name, role='attendee', pw=None): pwd = None if pw: pwd = pw elif self.meeting_info(id): minfo = self.meeting_info(id) if role == 'moderator': pwd = minfo.get_meetinginfo().get_moderatorpw() elif role == 'attendee': pwd = minfo.get_meetinginfo().get_attendeepw() if pwd: return self.bbb.get_join_meeting_url(name, id, pwd) def get_meetings(self, server): self.logger.debug("fetching meetings from {}".format(server)) try: meetingsXML = self.bbb.get_meetings() if meetingsXML.get_field('returncode') == 'SUCCESS': if meetingsXML.get_field('meetings') == '': self.logger.debug( "no meetings running on {}".format(server)) return [] else: rawMeetings = meetingsXML.get_field('meetings')['meeting'] if isinstance(rawMeetings, list): self.logger.debug( "meetings found on {}".format(server)) return json.loads(json.dumps(rawMeetings)) else: self.logger.debug("meeting found on {}".format(server)) return [json.loads(json.dumps(rawMeetings))] else: self.logger.error("api request failed") return [] except urllib.error.URLError as ERR: self.logger.error(ERR) return [] def find_meeting(self, server, title, user='******'): meetings = self.get_meetings(server) for meeting in meetings: if title in meeting['meetingName']: meeting['joinAttendeeUrl'] = self.get_join_url( meeting['meetingID'], user, 'attendee') meeting['joinModeratorUrl'] = self.get_join_url( meeting['meetingID'], user, 'moderator') joinParams = {} joinParams['meetingID'] = meeting['meetingID'] joinParams['fullName'] = user joinParams['password'] = meeting['attendeePW'] joinParams['userdata-bbb_auto_join_audio'] = "true" joinParams['userdata-bbb_enable_video'] = 'false' joinParams['userdata-bbb_listen_only_mode'] = "false" joinParams['userdata-bbb_skip_check_audio'] = 'true' meeting['joinDirectWithMicUrl'] = self.bbbUrl.buildUrl( "join", params=joinParams) return meeting def show_meetings(self, server, user='******'): meetings = self.get_meetings(server) for meeting in meetings: print(meeting['meetingName']) print("ID: {}".format(meeting['meetingID'])) print("ATTENDEE_PASSWORD: {}".format(meeting['attendeePW'])) joinAttendeeUrl = self.get_join_url(meeting['meetingID'], user, 'attendee') print("JOIN_ATTENDEE_URL: {}".format(joinAttendeeUrl)) print("MODERATOR_PASSWORD: {}".format(meeting['moderatorPW'])) joinModeratorUrl = self.get_join_url(meeting['meetingID'], user, 'moderator') print("JOIN_MODERATOR_URL: {}".format(joinModeratorUrl)) print("")
def __init__(self, bbbUrl, bbbSecret): logging.info("setup BBB connection") self.bbb = BigBlueButton(bbbUrl, bbbSecret)