İçerik güncellemesi / Bugfix

This commit is contained in:
abdussamedulutas 2025-12-07 13:57:08 +03:00
parent 5627d6adac
commit d98ec6330e
11 changed files with 1220 additions and 946 deletions

View File

@ -219,7 +219,12 @@ export default class Peer extends EventTarget
to: this.socketId to: this.socketId
}); });
}else{ }else{
this.rtc?.sendMessage(pack) if(pack.type != ':rtcpack:')
{
this.rtc?.sendMessage(pack)
}else{
return console.warn("Socket is not writable");
}
} }
} }
async forget(){ async forget(){

View File

@ -201,6 +201,7 @@ export default class WebRTC
}; };
sendingStream.senders = senders; sendingStream.senders = senders;
} }
this.emit('stream:accepted', sendingStream);
break; break;
} }
case "message":{ case "message":{

View File

@ -184,13 +184,13 @@ export default class MWSE extends EventTarget {
let peer = this.peer(from, true); let peer = this.peer(from, true);
peer.info.info = info; peer.info.info = info;
peer.emit("accepted/pair", peer); peer.emit("accepted/pair", peer);
this.peer('me').emit('accepted/pairr', peer); this.peer('me').emit('accepted/pair', peer);
}) })
this.EventPooling.signal("end/pair", (payload : {from : string,info: any}) => { this.EventPooling.signal("end/pair", (payload : {from : string,info: any}) => {
let {from, info} = payload; let {from, info} = payload;
let peer = this.peer(from, true); let peer = this.peer(from, true);
peer.emit("endPair", info); peer.emit("end/pair", info);
this.peer('me').emit('endPair', from, info); this.peer('me').emit('end/pair', from, info);
}) })
} }
public room(options: IRoomOptions | string) : Room public room(options: IRoomOptions | string) : Room

View File

@ -16,7 +16,7 @@ body{
height: 100%; height: 100%;
display: flex; display: flex;
flex-wrap: nowrap; flex-wrap: nowrap;
flex-direction: row; flex-direction: column;
box-sizing: border-box; box-sizing: border-box;
overflow: hidden; overflow: hidden;
} }
@ -140,3 +140,40 @@ video{
transition: width 0.05s linear; transition: width 0.05s linear;
} }
} }
.controllist{
display: flex;
flex-direction: row;
flex-wrap: nowrap;
gap: 12px;
flex: 1 1 auto;
}
.ctrl-btn {
width: 48px;
height: 48px;
border: 1px solid #ccc;
border-radius: 8px;
background: #fff;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: background 0.2s, border-color 0.2s;
}
.ctrl-btn:hover {
background: #f0f0f0;
border-color: #999;
}
.ctrl-btn .material-icons {
font-size: 26px;
}
.logo{
object-fit: contain;
max-height: 50px;
width: 100%;
background-color: white;
border-radius: 10px;
}

View File

@ -13,6 +13,34 @@
<div class="videolist"> <div class="videolist">
</div> </div>
<div style="display:flex;flex-direction: row;">
<div class="controllist">
<div style="flex:0 0 300px">
<img src="https://app.argist.com/img/argist-logo-yan.png" class="logo">
</div>
<div style="flex: 1 1 auto"></div>
<button class="ctrl-btn mic-on" title="Mikrofon Aç">
<span class="material-icons">mic</span>
</button>
<button class="ctrl-btn mic-off" title="Mikrofon Kapat" style="display:none">
<span class="material-icons">mic_off</span>
</button>
<button class="ctrl-btn cam-on" title="Kamera Aç" style="display:none">
<span class="material-icons">videocam</span>
</button>
<button class="ctrl-btn cam-off" title="Kamera Kapat">
<span class="material-icons">videocam_off</span>
</button>
<button class="ctrl-btn share-on" title="Ekran Paylaş">
<span class="material-icons">screen_share</span>
</button>
<button class="ctrl-btn share-off" title="Ekran Paylaşmayı Durdur" style="display:none">
<span class="material-icons">stop_screen_share</span>
</button>
<div style="flex: 1 1 auto"></div>
<div style="flex:0 0 300px"></div>
</div>
</div>
</div> </div>
<script src="./index.js?v=42"></script> <script src="./index.js?v=42"></script>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

View File

@ -31,7 +31,9 @@ let outgoingStream;
* @type {HTMLDivElement} * @type {HTMLDivElement}
*/ */
let videoContainer = document.querySelector(".videolist"); let videoContainer = document.querySelector(".videolist");
let maxbitrate; let amaxb;
let vmaxb;
let rate;
let resulation; let resulation;
let activePeers = {} let activePeers = {}
@ -60,6 +62,7 @@ document.addEventListener("click",()=>{
}) })
/** /**
* @type {HTMLVideoElement} * @type {HTMLVideoElement}
*/ */
@ -135,33 +138,25 @@ async function beginEngine()
myIPAddress = await mwse.virtualPressure.allocAPIPAddress(); myIPAddress = await mwse.virtualPressure.allocAPIPAddress();
myNumber = await mwse.virtualPressure.allocAPNumber(); myNumber = await mwse.virtualPressure.allocAPNumber();
roomid = url.searchParams.get("room"); roomid = url.searchParams.get("room");
user = url.searchParams.get("user") ?? "User";
vmaxb = url.searchParams.get("vmaxb") ?? 32_0000
amaxb = url.searchParams.get("amaxb") ?? 2500000
resulation = url.searchParams.get("resulation") ?? 1
rate = url.searchParams.get("rate") ?? 10
if(!!roomid == 0) if(!!roomid == 0)
{ {
let hash = window.crypto.randomUUID(); let hash = window.crypto.randomUUID();
url.searchParams.set("room", hash); url.searchParams.set("room", hash);
url.searchParams.set("vmaxb", vmaxb);
url.searchParams.set("amaxb", amaxb);
url.searchParams.set("resulation", resulation);
url.searchParams.set("rate", rate);
url.searchParams.set("user", user);
window.location = url.href; window.location = url.href;
}; };
connectRoom(roomid); connectRoom(roomid);
if(url.searchParams.get("maxbitrate"))
{
let n = Number(url.searchParams.get("maxbitrate"));
if(Number.isFinite(n) && !Number.isNaN(n))
{
maxbitrate = n;
}else maxbitrate = 2500_000;
}else maxbitrate = 2500_000;
if(url.searchParams.get("resulation"))
{
let n = Number(url.searchParams.get("resulation"));
if(Number.isFinite(n) && !Number.isNaN(n))
{
resulation = n;
}else resulation = 1.2;
}else resulation = 1.2;
}; };
window.addEventListener("load", () => { window.addEventListener("load", () => {
@ -241,15 +236,16 @@ async function IncomingPeer(peer,activeConnect)
urls: "stun:stun.l.google.com:19302" urls: "stun:stun.l.google.com:19302"
}]); }]);
if(activeConnect) if(peer.rtc.isPolite())
{ {
peer.rtc.connect(); peer.rtc.connect();
} }
peer.rtc.rtc.turboBitrate = 0; peer.rtc.rtc.turboBitrate = 0;
peer.rtc.on('connected',() => { peer.rtc.on('connected',() => {
if(!activeConnect) if(peer.rtc.isPolite())
{ {
peer.rtc.sendStream(outgoingStream, "Webcam", {}); peer.rtc.sendStream(outgoingStream, "Webcam", {});
activePeers[peer.socketId] = peer;
} }
}); });
peer.rtc.on('disconnected',() => { peer.rtc.on('disconnected',() => {
@ -264,9 +260,10 @@ async function IncomingPeer(peer,activeConnect)
void 0, void 0,
peer.info.get("name") peer.info.get("name")
); );
if(activeConnect) if(peer.rtc.isPolite() == false)
{ {
peer.rtc.sendStream(outgoingStream, "Webcam", {}); peer.rtc.sendStream(outgoingStream, "Webcam", {});
activePeers[peer.socketId] = peer;
} }
}) })
} }
@ -282,18 +279,32 @@ function OutgoingPeer(peer)
let relative; let relative;
setInterval(() => { setInterval(() => {
for(const [,peerRtc] of Object.entries(activePeers)) for(const [,peer] of Object.entries(activePeers))
{ {
if(peerRtc?.turboBitrate !== 1) let peerRtc = peer.rtc.rtc;
const senders = peerRtc.getSenders();
if(peerRtc.vturboBitrate !== 1)
{ {
const senders = peerRtc.getSenders();
const videoSender = senders.find(sender => sender.track?.kind === 'video'); const videoSender = senders.find(sender => sender.track?.kind === 'video');
if(videoSender){ if(videoSender){
const parameters = videoSender.getParameters(); const parameters = videoSender.getParameters();
parameters.encodings[0].maxBitrate = maxbitrate; parameters.encodings[0].maxBitrate = vmaxb;
parameters.encodings[0].scaleResolutionDownBy = resulation; parameters.encodings[0].scaleResolutionDownBy = resulation;
parameters.encodings[0].maxFramerate = rate;
videoSender.setParameters(parameters).then(() => { videoSender.setParameters(parameters).then(() => {
peerRtc.turboBitrate = 1; peerRtc.vturboBitrate = 1;
});
}
}
if(peerRtc.aturboBitrate !== 1)
{
const audioSender = senders.find(sender => sender.track?.kind === 'audio');
if(audioSender){
const parameters = audioSender.getParameters();
parameters.encodings[0].maxBitrate = amaxb;
audioSender.setParameters(parameters).then(() => {
peerRtc.aturboBitrate = 1;
}); });
} }
} }
@ -301,13 +312,6 @@ setInterval(() => {
},1000); },1000);
function bindAudioLevel(stream, element, options = {}) { function bindAudioLevel(stream, element, options = {}) {
const {
minPercent = 5,
maxPercent = 100,
decayRate = 0.97, // 0.90.99 arasında önerilir
volumeScale = 2.0 // gelen rms değerini büyütmek için (normalize daha geniş aralık)
} = options;
const audioCtx = new (window.AudioContext || window.webkitAudioContext)(); const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
const source = audioCtx.createMediaStreamSource(stream); const source = audioCtx.createMediaStreamSource(stream);
const analyser = audioCtx.createAnalyser(); const analyser = audioCtx.createAnalyser();

View File

@ -1,208 +1,175 @@
function HostListItem() /**
* =================================================================
* LİSANS BİLDİRİMİ -LGPL - LGPL-AU-EK
* =================================================================
* * Yazar (Original Author): Abdussamed ulutaş
* * İzinler (Permissions):
* ---------------------
* Bu kod, ticari veya kişisel amaçlarla serbestçe OKUNABILIR,
* KOPYALANABILIR, ÇOĞALTILABILIR, DEĞIŞTIRILEBILIR ve KULLANILABILIR.
* * * Koşul (Zorunlu Atıf Şartı - Attribution Requirement):
* ---------------------------------------------------
* Bu yazılımın temelindeki ANA ALGORITMA tamamen ve özgün bir şekilde değiştirilmediği sürece,
* "author by Abdussamed ulutaş" ifadesi kodun içerisinde MUTLAKA KORUNMALIDIR.
* * NOT: Algoritmanın temel mantığı korunarak yapılan küçük değişiklikler,
* optimizasyonlar veya arayüz entegrasyonları, bu atıf ifadesinin kaldırılması için yeterli sayılmaz.
* * * Sorumluluk Reddi (Disclaimer):
* ----------------------------
* Bu yazılım "olduğu gibi" (as-is) sağlanmıştır. Yazar, yazılımın kullanımından
* kaynaklanacak hiçbir zarardan sorumlu değildir.
* * =================================================================
*/
// Aşağıdaki satır, atıf şartını yerine getiren zorunlu ifadedir ve kodun içinde kalmalıdır:
//
// author by Abdussamed ulutaş
//
// =================================================================
/*
- Tüm dizinler herkese görünecek
- Dizinler ve dosyalar arayüzden tekrarlanamayacak
- Dosya ve klasör isimler aynı isimde olabilir
- Kimse bir başkasının dosyasını ve klasörünü silemez
- Yeni bir kişi bağlandığında dizin listesi eşitleniyor olacak
- Bağlanılan kişi ayrıldığında ona ait olan tüm dosya/dizin sistemi silinecek
*/
function é(rule)
{ {
let item = $(` if(é.element == null)
<tr> {
<td class="text-nowrap"> /** @type {HTMLStyleElement} */
<button class="btn btn-outline-primary btn-sm action-download"> é.element = document.createElement("style");
İndir document.head.appendChild(é.element);
</button> /** @type {CSSStyleSheet} */
<button class="btn btn-outline-danger btn-sm action-remove"> é.sheet = é.element.sheet;
Kaldır
</button>
</td>
<td class="text-nowrap">
<button class="btn btn-outline-secondary btn-sm action-sha1">
Hesapla
</button>
</td>
<td class="text-nowrap">
<span class="action-filename">DCIM_AMG_25TEM2025.png</span>
<br>
<span class="text-muted">
(Sizin cihazda)
</span>
</td>
<td class="text-nowrap">
<div class="progress" style="height:30px">
<div class="progress-bar" role="progressbar" aria-valuenow="20" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</td>
</tr>
`);
return {
download: item.find(".action-download"),
hide: item.find(".action-hide"),
remove: item.find(".action-remove"),
sha1: item.find(".action-sha1"),
filename: item.find(".action-filename"),
progress: item.find(".progress"),
container: item
} }
é.sheet.insertRule(rule);
} }
function RemoteListItem() é`html,body{
{ background-color: black;
let item = $(` height: 100%;
<tr> font-size: 14px;
<td class="text-nowrap"> > * {
<button class="btn btn-outline-primary btn-sm action-download"> box-sizing:border-box;
İndir
</button>
<button class="btn btn-outline-secondary btn-sm action-hide">
Gizle
</button>
</td>
<td class="text-nowrap">
<button class="btn btn-outline-secondary btn-sm action-sha1">
Hesapla
</button>
</td>
<td class="text-nowrap">
<span class="action-filename">DCIM.mp4</span>
<br>
<span class="text-muted">
(Karşı cihazda)
</span>
</td>
<td class="text-nowrap">
<div class="progress" style="height:30px">
<div class="progress-bar" role="progressbar" aria-valuenow="20" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</td>
</tr>
`);
return {
download: item.find(".action-download"),
hide: item.find(".action-hide"),
remove: item.find(".action-remove"),
sha1: item.find(".action-sha1"),
filename: item.find(".action-filename"),
progress: item.find(".progress"),
container: item
} }
} }`;
é`body{
display: flex;
flex-direction: row;
flex-wrap: nowrap;
padding: 20px;
overflow: hidden;
}`;
function EmptyListItem() é`@keyframes color-transition {
{ 0% {
return $(` color: #c8c8c8;
<tr> }
<td class="text-center text-muted" colspan="4"> 50% {
Gönderilecek veya alınacak dosya bulunmuyor color: #757575;
</td> }
</tr> 100% {
`) color: #c8c8c8;
} }
}`;
function formatBytes(a,b=2){if(!+a)return"0 Bytes";const c=0>b?0:b,d=Math.floor(Math.log(a)/Math.log(1024));return`${parseFloat((a/Math.pow(1024,d)).toFixed(c))} ${["Bytes","KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB"][d]}`} /// UI
// <span class="material-icons">
const endpoint = `wss://ws.saqut.com/socket/webserver/${("000000"+(Math.random() * 512 | 0)).slice(-6)}.sock`; const UIM = new class UI {
constructor(){
this.setup();
}
setup(){
this.setupOutContainer();
this.setupDirentContainer();
}
/** @type {JQuery} */
container = null;
setupOutContainer(){
this.container = $("<div>");
this.container.addClass("dip-fev");
é`.dip-fev{
width: 100%;
height: 100%;
background-color: rgba(255,255,255,0.2);
position: relative;
border-radius: 5px;
border: solid 1px rgba(255,255,255,0.1);
display: flex;
overflow: auto;
flex-direction: column;
flex-wrap: nowrap;
}`;
document.body.append(this.container.get(0));
}
/** @type {JQuery} */
direntbezier = null;
setupDirentContainer(){
this.direntbezier = $("<div>");
this.direntbezier.addClass("dip-bezier");
é`.dip-bezier{
flex: 0 0 auto;
background-color: rgba(255,255,255,0.2);
display: flex;
flex-direction: row;
flex-wrap: nowrap;
padding: 5px;
& > .dip-bezier-icon{
padding: 3px;
animation: color-transition 1s ease-in-out infinite;
}
& > .dip-bezier-disk{
color: white;
padding: 3px;
}
& > .dip-bezier-object{
color: white;
padding: 3px 2px;
cursor: pointer;
border-radius: 3px;
&:hover{
background-color: rgba(255,255,255,0.05);
}
}
& > .dip-bezier-splitter{
margin: 5px 2px;
width: 1px;
background-color: rgba(0,0,0,0.1);
}
}`;
this.container.append(this.direntbezier);
let mwse = new MWSE({ this.setupBezier("Diskim",["Resimler","Yakalamalar","Benim yakalamalarım"]);
endpoint, }
autoReconnect: true, setupBezier(disk, folders){
autoReconnectTimeout: 60_000 let icon = $("<span>");
}); icon.addClass("dip-bezier-icon material-symbols-outlined");
icon.text("bigtop_updates");
this.direntbezier.append(icon);
mwse.scope(Connect); let section = $("<div>");
section.addClass("dip-bezier-disk");
section.html(disk + " ://");
this.direntbezier.append(section);
let room; folders.map((element, index, array) => {
let ip; let section = $("<div>");
section.addClass("dip-bezier-object");
async function Connect() section.text(element);
{ this.direntbezier.append(section);
await genRoom(); if(index < array.length - 1)
$(".network-id").text(ip); {
} let sectionPadding = $("<div>");
sectionPadding.addClass("dip-bezier-splitter");
async function genRoom() this.direntbezier.append(sectionPadding);
{ }
do{
let vip = ip = [
(Math.random() * 16 | 0) + 10,
(Math.random() * 8 | 0),
(Math.random() * 4 | 0),
(Math.random() * 254 | 0) + 1
].join('.');
room = mwse.room({
name: `WEB3-Smash [${vip}] RO CONNECT:2`,
description: "Web3 Smash saQut Server Application",
joinType: "free",
notifyActionJoined: true,
notifyActionEjected: true,
ifexistsJoin: false
}); });
try{ }
await room.createRoom();
break;
}catch{
continue;
}
}while(1);
} }
class FileDescriptor {
static hostfiles = new Map();
static remotefiles = new Map();
static hostindex = 0;
static remoteindex = 0;
file = null;
listItem = null;
constructor(isHost, item,file){
this.file = file;
this.listItem = item;
$("#thelist").append(item.container);
if(isHost)
{
FileDescriptor.hostfiles.set(
++FileDescriptor.hostindex,
this
);
}else{
FileDescriptor.remotefiles.set(
++FileDescriptor.remoteindex,
this
);
}
this.init();
}
init(){
this.listItem.filename.html(
this.file.name + " <span class='text-muted'>" + formatBytes(this.file.size) + "</span>"
);
}
};
$("#files").on('change',function(){
for (const file of this.files) {
$("#thelist .empty").remove();
new FileDescriptor(
true,
HostListItem(),
file
)
};
$("#files").val('');
});
$(".joinroom").on("chnage",function(){
let ip = $("#remoteadress").val();
if(!/^\d+\.\d+\.\d+$/.test(ip)){
return alert(" ")
}
$("#thelist .empty").remove();
room = mwse.room({
name: `WEB3-Smash [${vip}] RO CONNECT:2`,
description: "Web3 Smash saQut Server Application",
joinType: "free",
notifyActionJoined: true,
notifyActionEjected: true,
ifexistsJoin: false
});
})

27
public/m.h.2.8.9.js Normal file
View File

@ -0,0 +1,27 @@
/**
* =================================================================
* LİSANS BİLDİRİMİ - LGPL - LGPL-AU-EK
* =================================================================
* * Yazar (Original Author): Abdussamed ulutaş
* * İzinler (Permissions):
* ---------------------
* Bu kod, ticari veya kişisel amaçlarla serbestçe OKUNABILIR,
* KOPYALANABILIR, ÇOĞALTILABILIR, DEĞIŞTIRILEBILIR ve KULLANILABILIR.
* * * Koşul (Zorunlu Atıf Şartı - Attribution Requirement):
* ---------------------------------------------------
* Bu yazılımın temelindeki ANA ALGORITMA tamamen ve özgün bir şekilde değiştirilmediği sürece,
* "author by Abdussamed ulutaş" ifadesi kodun içerisinde MUTLAKA KORUNMALIDIR.
* * NOT: Algoritmanın temel mantığı korunarak yapılan küçük değişiklikler,
* optimizasyonlar veya arayüz entegrasyonları, bu atıf ifadesinin kaldırılması için yeterli sayılmaz.
* * * Sorumluluk Reddi (Disclaimer):
* ----------------------------
* Bu yazılım "olduğu gibi" (as-is) sağlanmıştır. Yazar, yazılımın kullanımından
* kaynaklanacak hiçbir zarardan sorumlu değildir.
* * =================================================================
*/
// Aşağıdaki satır, atıf şartını yerine getiren zorunlu ifadedir ve kodun içinde kalmalıdır:
//
// author by Abdussamed ulutaş
//
// =================================================================

View File

@ -6,58 +6,10 @@
<title>Dosya Transfer Sistem</title> <title>Dosya Transfer Sistem</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.7/css/bootstrap.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.7/css/bootstrap.min.css">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined" />
</head> </head>
<body> <body>
<div class="container" style="max-width: 1200px">
<h2 class="text-center mb-2 mt-5">Dosya Transfer Sistemi</h2>
<h1 class="text-center mb-5 mt-3 text-bold fw-bold">
<span>Ağ Adresiniz</span>
<span class="text-danger network-id">
#.#.#.#
</span>
</h1>
<div class="mx-auto d-flex flex-row mb-5" style="max-width: 800px;gap:20px">
<div class="flex-fill">
<input
type="file"
id="files"
multiple
class="form-control"
>
</div>
<div class="flex-fill d-flex" style="gap:5px">
<input
type="text"
class="form-control"
placeholder="Farklı bir ağa katıl"
id="remoteadress"
>
<button class="btn btn-outline-success joinroom">
Katıl
</button>
</div>
</div>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th class="text-nowrap" width="1%">İşlem</th>
<th class="text-nowrap" width="1%">SHA-1</th>
<th class="text-nowrap" width="49%">Dosya İsmi</th>
<th class="text-nowrap" width="50%">İşlem</th>
</tr>
</thead>
<tbody id="thelist">
<tr class="empty">
<td class="text-center text-muted" colspan="4">
Gönderilecek veya alınacak dosya bulunmuyor
</td>
</tr>
</tbody>
</table>
</div>
<script src="https://ws.saqut.com/script"></script> <script src="https://ws.saqut.com/script"></script>
<script src="m.h.2.8.8.js"></script> <script src="m.h.2.8.8.js"></script>
</body> </body>

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long