diff --git a/base/__pycache__/__init__.cpython-313.pyc b/base/__pycache__/__init__.cpython-313.pyc
new file mode 100644
index 0000000..aab3819
Binary files /dev/null and b/base/__pycache__/__init__.cpython-313.pyc differ
diff --git a/base/__pycache__/admin.cpython-313.pyc b/base/__pycache__/admin.cpython-313.pyc
new file mode 100644
index 0000000..10e0cd0
Binary files /dev/null and b/base/__pycache__/admin.cpython-313.pyc differ
diff --git a/base/__pycache__/apps.cpython-313.pyc b/base/__pycache__/apps.cpython-313.pyc
new file mode 100644
index 0000000..42ce66b
Binary files /dev/null and b/base/__pycache__/apps.cpython-313.pyc differ
diff --git a/base/__pycache__/models.cpython-313.pyc b/base/__pycache__/models.cpython-313.pyc
new file mode 100644
index 0000000..97fb24b
Binary files /dev/null and b/base/__pycache__/models.cpython-313.pyc differ
diff --git a/base/__pycache__/urls.cpython-313.pyc b/base/__pycache__/urls.cpython-313.pyc
new file mode 100644
index 0000000..9ebec5d
Binary files /dev/null and b/base/__pycache__/urls.cpython-313.pyc differ
diff --git a/base/__pycache__/views.cpython-313.pyc b/base/__pycache__/views.cpython-313.pyc
new file mode 100644
index 0000000..8a8322c
Binary files /dev/null and b/base/__pycache__/views.cpython-313.pyc differ
diff --git a/base/migrations/__pycache__/__init__.cpython-313.pyc b/base/migrations/__pycache__/__init__.cpython-313.pyc
new file mode 100644
index 0000000..4280a65
Binary files /dev/null and b/base/migrations/__pycache__/__init__.cpython-313.pyc differ
diff --git a/base/templates/base/lobby.html b/base/templates/base/lobby.html
index a390c32..2dce955 100644
--- a/base/templates/base/lobby.html
+++ b/base/templates/base/lobby.html
@@ -1,7 +1,7 @@
{% extends 'base/main.html' %}
{% load static %}
-
{% block content %}
+
-{% endblock content %}
\ No newline at end of file
+
+
+
+{% endblock content %}
diff --git a/base/templates/base/room.html b/base/templates/base/room.html
index 2061dec..fbf8a58 100644
--- a/base/templates/base/room.html
+++ b/base/templates/base/room.html
@@ -1,18 +1,19 @@
{% extends 'base/main.html' %}
-
{% block content %}
-
- Room Name:
+
-
-
+
+
+
+
+
+
{% endblock content %}
+
diff --git a/base/urls.py b/base/urls.py
index eee9bea..9dbd17b 100644
--- a/base/urls.py
+++ b/base/urls.py
@@ -1,7 +1,8 @@
-from django.urls import path
-from . import views
+from django.urls import path
+from . import views
urlpatterns = [
- path("", views.lobby),
- path("room/", views.room),
+ path('', views.lobby),
+ path('room/', views.room),
+ path('get_token/', views.getToken),
]
diff --git a/base/views.py b/base/views.py
index bf673c6..0ff600a 100644
--- a/base/views.py
+++ b/base/views.py
@@ -1,7 +1,25 @@
from django.shortcuts import render
+from django.http import JsonResponse
+import random
+import time
+from agora_token_builder import RtcTokenBuilder
def lobby(request):
return render(request, 'base/lobby.html')
def room(request):
return render(request, 'base/room.html')
+
+def getToken(request):
+ appId = 'YOUR_AGORA_APP_ID'
+ appCertificate = 'YOUR_AGORA_APP_CERTIFICATE'
+ channelName = request.GET.get('channel')
+ uid = random.randint(1, 230)
+ expirationTimeInSeconds = 3600 * 24
+ currentTimeStamp = int(time.time())
+ privilegeExpiredTs = currentTimeStamp + expirationTimeInSeconds
+ role = 1
+
+ token = RtcTokenBuilder.buildTokenWithUid(appId, appCertificate, channelName, uid, role, privilegeExpiredTs)
+
+ return JsonResponse({'token': token, 'uid': uid}, safe=False)
diff --git a/mychart/__pycache__/__init__.cpython-313.pyc b/mychart/__pycache__/__init__.cpython-313.pyc
new file mode 100644
index 0000000..292ca43
Binary files /dev/null and b/mychart/__pycache__/__init__.cpython-313.pyc differ
diff --git a/mychart/__pycache__/settings.cpython-313.pyc b/mychart/__pycache__/settings.cpython-313.pyc
new file mode 100644
index 0000000..7242c19
Binary files /dev/null and b/mychart/__pycache__/settings.cpython-313.pyc differ
diff --git a/mychart/__pycache__/urls.cpython-313.pyc b/mychart/__pycache__/urls.cpython-313.pyc
new file mode 100644
index 0000000..fdff78a
Binary files /dev/null and b/mychart/__pycache__/urls.cpython-313.pyc differ
diff --git a/mychart/__pycache__/wsgi.cpython-313.pyc b/mychart/__pycache__/wsgi.cpython-313.pyc
new file mode 100644
index 0000000..6748f49
Binary files /dev/null and b/mychart/__pycache__/wsgi.cpython-313.pyc differ
diff --git a/static/js/stream.js b/static/js/stream.js
index e69de29..4b7ea00 100644
--- a/static/js/stream.js
+++ b/static/js/stream.js
@@ -0,0 +1,98 @@
+const APP_ID = 'YOUR_AGORA_APP_ID'
+const CHANNEL = sessionStorage.getItem('room')
+const TOKEN = sessionStorage.getItem('token')
+let UID = Number(sessionStorage.getItem('uid'))
+
+const client = AgoraRTC.createClient({mode:'rtc', codec:'vp8'})
+
+let localTracks = []
+let remoteUsers = {}
+
+let joinAndDisplayLocalStream = async () => {
+ document.getElementById('room-name-wrapper').innerText = CHANNEL
+
+ client.on('user-published', handleUserJoined)
+ client.on('user-left', handleUserLeft)
+
+ try{
+ await client.join(APP_ID, CHANNEL, TOKEN, UID)
+ }catch(error){
+ console.error(error)
+ window.open('/', '_self')
+ }
+
+ localTracks = await AgoraRTC.createMicrophoneAndCameraTracks()
+
+ let player = `
`
+ document.getElementById('video-streams').insertAdjacentHTML('beforeend', player)
+
+ localTracks[1].play(`user-${UID}`)
+ await client.publish([localTracks[0], localTracks[1]])
+}
+
+let handleUserJoined = async (user, mediaType) => {
+ remoteUsers[user.uid] = user
+ await client.subscribe(user, mediaType)
+
+ if (mediaType === 'video'){
+ let player = document.getElementById(`user-container-${user.uid}`)
+ if (player != null){
+ player.remove()
+ }
+
+ player = ``
+ document.getElementById('video-streams').insertAdjacentHTML('beforeend', player)
+ user.videoTrack.play(`user-${user.uid}`)
+ }
+
+ if (mediaType === 'audio'){
+ user.audioTrack.play()
+ }
+}
+
+let handleUserLeft = async (user) => {
+ delete remoteUsers[user.uid]
+ document.getElementById(`user-container-${user.uid}`).remove()
+}
+
+let leaveAndRemoveLocalStream = async () => {
+ for(let i = 0; localTracks.length > i; i++){
+ localTracks[i].stop()
+ localTracks[i].close()
+ }
+
+ await client.leave()
+ window.open('/', '_self')
+}
+
+let toggleMic = async (e) => {
+ if (localTracks[0].muted){
+ await localTracks[0].setMuted(false)
+ e.target.innerText = 'Mute Mic'
+ }else{
+ await localTracks[0].setMuted(true)
+ e.target.innerText = 'Unmute Mic'
+ }
+}
+
+let toggleCamera = async (e) => {
+ if (localTracks[1].muted){
+ await localTracks[1].setMuted(false)
+ e.target.innerText = 'Turn Off Camera'
+ }else{
+ await localTracks[1].setMuted(true)
+ e.target.innerText = 'Turn On Camera'
+ }
+}
+
+joinAndDisplayLocalStream()
+
+document.getElementById('leave-btn').addEventListener('click', leaveAndRemoveLocalStream)
+document.getElementById('mic-btn').addEventListener('click', toggleMic)
+document.getElementById('camera-btn').addEventListener('click', toggleCamera)