Compare commits

...
Sign in to create a new pull request.

128 commits

Author SHA1 Message Date
Lanta
7fd84e8bed
Merge pull request #278 from OpzekerIT/dev
error afhandeling
2026-01-29 18:04:06 +01:00
Lanta
5691559437 error afhandeling 2026-01-29 18:03:24 +01:00
Lanta
5b2de5199b
Merge pull request #277 from OpzekerIT/dev
loterij
2026-01-29 10:58:48 +01:00
Lanta
3f2a210486 loterij 2026-01-29 10:57:07 +01:00
Lanta
355f2e8868
Merge pull request #276 from OpzekerIT/dev
Dev
2025-10-17 13:39:18 +02:00
Lanta
ca8ae31e9e win filter 2025-10-17 13:37:45 +02:00
Lanta
c4ed5551ae tdm 2025-10-17 13:37:34 +02:00
Lanta
d286bc6079
Merge pull request #275 from OpzekerIT/dev
tdm
2025-10-08 16:36:19 +02:00
Lanta
20a050148b tdm 2025-10-08 16:35:48 +02:00
Lanta
8859b603dc
Merge pull request #274 from OpzekerIT/dev
tdm be gone
2025-10-08 16:32:03 +02:00
Lanta
8499e9f073 tdm be gone 2025-10-08 16:31:19 +02:00
Lanta
209cb5f86a
Merge pull request #273 from OpzekerIT/dev
s
2025-10-08 15:55:36 +02:00
Lanta
c175319cd9 s 2025-10-08 15:54:39 +02:00
Lanta
633ab16523
Merge pull request #272 from OpzekerIT/dev
geen events
2025-10-08 15:33:56 +02:00
Lanta
890d445c78 geen events 2025-10-08 15:22:32 +02:00
Lanta
f60ac1d44d
Merge pull request #271 from OpzekerIT/dev
s
2025-10-06 09:43:42 +02:00
Lanta
cf975bccce s 2025-10-06 09:40:51 +02:00
Lanta
99a15ae703
Merge pull request #270 from OpzekerIT/dev
prompt
2025-10-06 09:34:36 +02:00
Lanta
4ce21087f4 prompt 2025-10-06 09:33:57 +02:00
Lanta
c52eaa61a4
Merge pull request #269 from OpzekerIT/dev
betere system prompt
2025-10-03 12:15:14 +02:00
Lanta
c724cd6bcb betere system prompt 2025-10-03 12:14:45 +02:00
Lanta
190e774739
Merge pull request #268 from OpzekerIT/dev
options not supported
2025-10-03 09:05:40 +02:00
Lanta
0870891747 options not supported 2025-10-03 09:05:16 +02:00
Lanta
48df01a3f6
Merge pull request #267 from OpzekerIT/dev
rate limit
2025-10-03 09:04:43 +02:00
Lanta
a36425d798 rate limit 2025-10-03 09:03:31 +02:00
Lanta
e8c0bd148d
Merge pull request #266 from OpzekerIT/dev
temp
2025-10-03 08:59:51 +02:00
Lanta
8fdc97067a temp 2025-10-03 08:55:47 +02:00
Lanta
29e370bbc2
Merge pull request #265 from OpzekerIT/dev
voice online
2025-10-02 21:36:42 +02:00
Lanta
5d2258ca1d voice online 2025-10-02 21:36:03 +02:00
Lanta
b2f6202d8d
Merge pull request #264 from OpzekerIT/dev
up
2025-10-02 21:32:42 +02:00
Lanta
2c1f956938 up 2025-10-02 21:32:18 +02:00
Lanta
1168fa4101
Merge pull request #263 from OpzekerIT/dev
s
2025-10-02 21:03:29 +02:00
Lanta
e8e4d3bcf7 s 2025-10-02 21:02:44 +02:00
Lanta
5c81889587
Merge pull request #262 from OpzekerIT/dev
onnline members in context
2025-10-02 20:53:56 +02:00
Lanta
d33030c746 onnline members in context 2025-10-02 20:52:50 +02:00
Lanta
71e32fcdb3
Merge pull request #261 from OpzekerIT/dev
Dev
2025-10-02 17:47:24 +02:00
Lanta
94c57710db context anders 2025-10-02 17:46:43 +02:00
Lanta
4c347e42af typing 2025-10-02 17:46:05 +02:00
Lanta
f106fd60c0
Merge pull request #260 from OpzekerIT/dev
s
2025-10-02 17:23:46 +02:00
Lanta
5993f6fd76 s 2025-10-02 17:22:17 +02:00
Lanta
3a395a9f61
Merge pull request #259 from OpzekerIT/dev
Dev
2025-10-02 17:18:20 +02:00
Lanta
ab8378f550 s 2025-10-02 17:17:32 +02:00
Lanta
8d7a838237 gpt 5 nano 2025-10-02 17:15:48 +02:00
Lanta
76bb2705b1
Merge pull request #258 from OpzekerIT/dev
meer stats
2025-10-02 17:00:26 +02:00
Lanta
596d7514a8 meer stats 2025-10-02 16:59:02 +02:00
Lanta
b1d7c40bb6
Merge pull request #257 from OpzekerIT/dev
Dev
2025-10-02 16:37:09 +02:00
Lanta
2b584df1a2 squad stats 2025-10-02 16:36:33 +02:00
Lanta
fbfde36813 squad 2025-10-02 16:36:16 +02:00
Lanta
de99550450
Merge pull request #256 from OpzekerIT/dev
clanmembers:
2025-10-02 16:24:03 +02:00
Lanta
65ebc9784f clanmembers: 2025-10-02 16:23:05 +02:00
Lanta
f70fba9d85
Merge pull request #255 from OpzekerIT/dev
Dev
2025-10-02 16:08:15 +02:00
Lanta
88cace125c s 2025-10-02 16:07:41 +02:00
Lanta
78debfcb09 s 2025-10-02 16:07:21 +02:00
Lanta
68381f3f3d
Merge pull request #254 from OpzekerIT/dev
opgegeven pars
2025-10-02 16:01:27 +02:00
Lanta
775d332f02 opgegeven pars 2025-10-02 16:00:50 +02:00
Lanta
cf72aa9c9e
Merge pull request #253 from OpzekerIT/dev
Dev
2025-10-02 15:47:47 +02:00
Lanta
466235dd25 ai 2025-10-02 15:47:14 +02:00
Lanta
5ef611c727 topx 2025-10-02 15:46:44 +02:00
Lanta
9c4fd72319
Merge pull request #252 from OpzekerIT/dev
ahd
2025-10-02 15:32:56 +02:00
Lanta
afed25d8ee ahd 2025-10-02 15:31:49 +02:00
Lanta
3a12f8c4c5
Merge pull request #251 from OpzekerIT/dev
Dev
2025-10-02 15:27:39 +02:00
Lanta
4757ccc9cb s 2025-10-02 15:27:13 +02:00
Lanta
c2487ade22 s 2025-10-02 15:26:57 +02:00
Lanta
ca365704f4
Merge pull request #250 from OpzekerIT/dev
stats test
2025-10-02 15:23:55 +02:00
Lanta
837f136b70 stats test 2025-10-02 15:23:13 +02:00
Lanta
7d3cbe24e1
Merge pull request #249 from OpzekerIT/dev
vraag antwoord direkt
2025-10-02 14:40:27 +02:00
Lanta
046691b068 vraag antwoord direkt 2025-10-02 14:39:15 +02:00
Lanta
db68e66ba3
Merge pull request #248 from OpzekerIT/dev
Dev
2025-10-02 14:30:12 +02:00
Lanta
2a80f52c9a discord bot 2025-10-02 14:29:30 +02:00
Lanta
83922cac1d lanta01 goed 2025-10-02 14:28:49 +02:00
Lanta
45428464fb
Merge pull request #247 from OpzekerIT/dev
denigrerende
2025-10-02 14:20:01 +02:00
Lanta
bdcad50f98 denigrerende 2025-10-02 14:17:58 +02:00
Lanta
967f79071b
Merge pull request #246 from OpzekerIT/dev
AI
2025-10-02 14:08:00 +02:00
Lanta
b4036047c7 AI 2025-10-02 14:07:40 +02:00
Lanta
294dda5354
Merge pull request #245 from OpzekerIT/dev
beh
2025-10-02 13:45:24 +02:00
Lanta
d1b153c322 beh 2025-10-02 13:44:52 +02:00
Lanta
db6e770bf9
Merge pull request #244 from OpzekerIT/dev
kanaalid
2025-10-02 13:42:33 +02:00
Lanta
7d48158e57 kanaalid 2025-10-02 13:41:41 +02:00
Lanta
7c0e9558f5
Merge pull request #243 from OpzekerIT/dev
return
2025-10-02 13:37:30 +02:00
Lanta
9794e9337a return 2025-10-02 13:37:06 +02:00
Lanta
91e04d849a
Merge pull request #242 from OpzekerIT/dev
Dev
2025-10-02 13:34:34 +02:00
Lanta
91b2a4cb40 ben er weer 2025-10-02 13:34:01 +02:00
Lanta
c82b1cd5ea text 2025-10-02 13:30:47 +02:00
Lanta
fe62e841e5 new member 2025-10-02 13:28:28 +02:00
Lanta
a59812f4ad
Merge pull request #241 from OpzekerIT/dev
dtch help
2025-10-02 13:21:48 +02:00
Lanta
4d02286ce2 dtch help 2025-10-02 13:21:24 +02:00
Lanta
4f1bc5d7c1
Merge pull request #240 from OpzekerIT/dev
help command
2025-10-02 12:00:47 +02:00
Lanta
872b87ee09 help command 2025-10-02 12:00:09 +02:00
Lanta
1e09e73ac2
Merge pull request #239 from OpzekerIT/dev
tourists
2025-10-02 10:56:52 +02:00
Lanta
56f40244c0 tourists 2025-10-02 10:54:15 +02:00
Lanta
62cc56a4af
Merge pull request #238 from OpzekerIT/dev
clanmember change
2025-09-23 12:35:39 +02:00
Lanta
7359204a9a clanmember change 2025-09-23 12:32:46 +02:00
Lanta
51bfc37ef8
Merge pull request #237 from OpzekerIT/dev
winwithurl
2025-06-19 11:24:27 +02:00
Lanta
21dd9b990b winwithurl 2025-06-19 11:23:58 +02:00
Lanta
e9991c9b31
Merge pull request #236 from OpzekerIT/dev
to pubg meta
2025-06-18 14:21:34 +02:00
Lanta
d6d9ada748 to pubg meta 2025-06-18 14:19:58 +02:00
Lanta
37e652a830
Merge pull request #235 from OpzekerIT/dev
Ghost_0223
2025-06-18 14:14:50 +02:00
Lanta
b3918e611d Ghost_0223 2025-06-18 14:13:42 +02:00
Lanta
1ab0947d12
Merge pull request #234 from OpzekerIT/dev
Theater modus
2025-06-17 19:49:08 +02:00
Lanta
f72fb0bb7d theather modus 2025-06-17 19:46:03 +02:00
Lanta
ff327d1886 theathermode 2025-06-17 19:25:00 +02:00
Lanta
af8c9ff61a video format 2025-06-17 19:11:09 +02:00
Lanta
7ef1ade9e0 theater modus 2025-06-17 18:48:52 +02:00
Lanta
fd190d2636 video dingen 2025-06-17 18:35:42 +02:00
Lanta
a76dce010d
Merge pull request #233 from OpzekerIT/dev
2d url fix
2025-06-17 17:46:16 +02:00
Lanta
dbf36ec5db 2d url fix 2025-06-17 17:45:38 +02:00
Lanta
962abb6eab
Merge pull request #232 from OpzekerIT/dev
Dev
2025-06-17 16:51:14 +02:00
Lanta
0eb08f3d2f k 2025-06-17 16:46:51 +02:00
Lanta
05796a7881 videos 2025-06-17 16:37:38 +02:00
Lanta
136c5f47d2 videos 2025-06-17 16:28:35 +02:00
Lanta
655371f229
Merge pull request #231 from OpzekerIT/dev
fix
2025-04-18 20:51:24 +02:00
Lanta
a496c39b3e fix 2025-04-18 20:50:51 +02:00
Lanta
b29cf11c87
Merge pull request #230 from OpzekerIT/dev
wtf is hier gebeurd ?!
2025-04-18 20:43:14 +02:00
Lanta
4001cde34f wtf is hier gebeurd ?! 2025-04-18 20:42:35 +02:00
Lanta
a3de04bbfb
Merge pull request #229 from OpzekerIT/dev
fix for win matches
2025-04-18 20:36:15 +02:00
Lanta
0d7981091b fix 2025-04-18 20:35:21 +02:00
Lanta
cdd9750089 losers be gone 2025-04-18 13:11:34 +02:00
Lanta
2c9b875831
Merge pull request #228 from OpzekerIT/dev
disable losers
2025-04-18 13:09:02 +02:00
Lanta
db3cc79398 disable losers 2025-04-18 13:08:25 +02:00
Lanta
f79cc64dca
Merge pull request #227 from OpzekerIT/dev
payloud empty
2025-04-18 13:05:55 +02:00
Lanta
32c2b51666 payloud empty 2025-04-18 13:05:11 +02:00
Lanta
411fbf0059
Merge pull request #226 from OpzekerIT/dev
debugging
2025-04-18 12:07:05 +02:00
Lanta
6de61e5ee0 debugging 2025-04-18 12:06:26 +02:00
Lanta
0aaea5306f
Merge pull request #225 from OpzekerIT/dev
fix
2025-04-15 19:15:08 +02:00
Lanta
9529f95c01 fix 2025-04-15 19:14:41 +02:00
Lanta
c3964d12e2
Merge pull request #224 from OpzekerIT/dev
Dev
2025-04-15 19:08:54 +02:00
Lanta
65fa001a18 test 2025-04-15 19:08:22 +02:00
Lanta
48ede491fa Force empty commit voor PR 2025-04-15 19:02:45 +02:00
10 changed files with 691 additions and 156 deletions

View file

@ -12,11 +12,12 @@
"THAIlux",
"Reijn7000",
"McPikkie",
"Brabo-Gamer",
"SquadKiller101",
"HeteKip",
"Pettie1972",
"Reijn7000"
"Reijn7001",
"Ghost_0223",
"Bossoemang"
],
"alts": [

View file

@ -24,7 +24,7 @@ if ($fileContent -match "\`$apiKey\s*=\s*\'([^\']+)\'") {
$apiKey = $matches[1]
}
else {
Write-Output "API Key not found"
write-output "API Key not found"
}
$headers = @{
@ -38,15 +38,17 @@ $fileContent = Get-Content -Path "$scriptroot/../discord/config.php" -Raw
# Use regex to match the apiKey value
if ($fileContent -match "\`$webhookurl\s*=\s*'([^']+)'") {
$webhookurl = $matches[1]
} else {
Write-Output "No web url found"
}
else {
write-output "No web url found"
}
# Use regex to match the losers webhook url
if ($fileContent -match "\`$webhookurl_losers\s*=\s*'([^']+)'") {
$webhookurl_losers = $matches[1]
} else {
Write-Output "No losers web url found"
}
else {
write-output "No losers web url found"
}
function send-discord {
@ -69,7 +71,13 @@ function send-discord-losers {
$payload = [PSCustomObject]@{
content = $content
}
if ($payload.content -eq "") {
$payload = [PSCustomObject]@{
content = "Nothing to report"
}
}
Invoke-RestMethod -Uri $webhookurl_losers -Method Post -Body ($payload | ConvertTo-Json) -ContentType 'Application/Json'
}
$map_map = @{
@ -91,142 +99,142 @@ try {
$player_matches = get-content "$scriptroot/../data/player_matches.json" | convertfrom-json -Depth 100
}
catch {
Write-Output 'Unable to read file exitin'
write-output 'Unable to read file exitin'
}
Write-Output $player_matches
Write-Output $new_win_matches
$new_win_matches = $player_matches[-1].new_win_matches
write-output $player_matches
write-output $new_win_matches
$new_win_matches = $player_matches[-2].new_win_matches
# Gebruik nu de lijst van nieuwe verloren matches uit het JSON-bestand
$new_loss_matches = $player_matches[-1].new_loss_matches
# Post verloren matches naar #losers kanaal
foreach ($lossid in $new_loss_matches) {
$lossmatch = $player_matches.player_matches | Where-Object { $_.id -eq $lossid }
if ($null -eq $lossmatch) { continue }
if ($lossmatch[0].gameMode -eq 'tdm') { continue }
# foreach ($lossid in $new_loss_matches) {
# $lossmatch = $player_matches.player_matches | Where-Object { $_.id -eq $lossid }
# if ($null -eq $lossmatch) { continue }
# if ($lossmatch[0].gameMode -eq 'tdm') { continue }
# Fetch detailed match stats and telemetry for the loss
$loss_match_stats = $null
$loss_telemetry = $null
try {
$loss_match_stats = Invoke-RestMethod -Uri "https://api.pubg.com/shards/steam/matches/$lossid" -Method GET -Headers $headers
$loss_telemetry = (invoke-webrequest @($lossmatch.telemetry_url)[0]).content | convertfrom-json | where-object { ($_._T -eq 'LOGPLAYERTAKEDAMAGE') -or ($_._T -eq 'LOGPLAYERKILLV2') }
} catch {
$errorMessage = $_.Exception.Message
Write-Warning ("Failed to fetch API/telemetry data for loss match {0}: {1}" -f $lossid, $errorMessage)
}
# # Fetch detailed match stats and telemetry for the loss
# $loss_match_stats = $null
# $loss_telemetry = $null
# try {
# $loss_match_stats = Invoke-RestMethod -Uri "https://api.pubg.com/shards/steam/matches/$lossid" -Method GET -Headers $headers
# $loss_telemetry = (invoke-webrequest @($lossmatch.telemetry_url)[0]).content | convertfrom-json | where-object { ($_._T -eq 'LOGPLAYERTAKEDAMAGE') -or ($_._T -eq 'LOGPLAYERKILLV2') }
# } catch {
# $errorMessage = $_.Exception.Message
# Write-Warning ("Failed to fetch API/telemetry data for loss match {0}: {1}" -f $lossid, $errorMessage)
# }
$loss_stats_table = @()
$loss_victims = @() # For team damage
# $loss_stats_table = @()
# $loss_victims = @() # For team damage
# Iterate through players found in the locally stored match data for this loss
foreach ($player_stat in $lossmatch[0].stats) {
$player_name = $player_stat.name
# Find the corresponding detailed stats from the API response
$detailed_player_stats = $null
if ($null -ne $loss_match_stats) {
$detailed_player_stats = $loss_match_stats.included | Where-Object {$_.type -eq 'participant'} | ForEach-Object {$_.attributes.stats} | Where-Object { $_.name -eq $player_name }
}
# # Iterate through players found in the locally stored match data for this loss
# foreach ($player_stat in $lossmatch[0].stats) {
# $player_name = $player_stat.name
# # Find the corresponding detailed stats from the API response
# $detailed_player_stats = $null
# if ($null -ne $loss_match_stats) {
# $detailed_player_stats = $loss_match_stats.included | Where-Object {$_.type -eq 'participant'} | ForEach-Object {$_.attributes.stats} | Where-Object { $_.name -eq $player_name }
# }
if ($null -eq $detailed_player_stats) {
Write-Warning "Could not find detailed stats for player $player_name in loss match $lossid. Using basic stats."
# Fallback to basic stats if detailed stats are missing
$loss_stats_table += [PSCustomObject]@{
Name = $player_name
'Human dmg' = "N/A"
'Human Kills' = "N/A"
'Dmg' = "$([math]::Round($player_stat.damageDealt))" # Use basic stat
'Kills' = "$($player_stat.kills)" # Use basic stat
'alive' = "$([math]::Round(($player_stat.timeSurvived / 60)))" # Use basic stat
}
continue # Skip telemetry processing if detailed stats failed
}
# if ($null -eq $detailed_player_stats) {
# Write-Warning "Could not find detailed stats for player $player_name in loss match $lossid. Using basic stats."
# # Fallback to basic stats if detailed stats are missing
# $loss_stats_table += [PSCustomObject]@{
# Name = $player_name
# 'Human dmg' = "N/A"
# 'Human Kills' = "N/A"
# 'Dmg' = "$([math]::Round($player_stat.damageDealt))" # Use basic stat
# 'Kills' = "$($player_stat.kills)" # Use basic stat
# 'alive' = "$([math]::Round(($player_stat.timeSurvived / 60)))" # Use basic stat
# }
# continue # Skip telemetry processing if detailed stats failed
# }
# Calculate stats (similar to win stats calculation)
$human_dmg = "N/A"
$human_kills = "N/A"
if ($null -ne $loss_telemetry) {
try {
$human_dmg = [math]::Round(($loss_telemetry | Where-Object { $_._T -eq 'LOGPLAYERTAKEDAMAGE' -and $_.attacker.name -eq $player_name -and $_.victim.accountId -notlike "ai.*" -and $_.victim.teamId -ne $_.attacker.teamId } | Measure-Object -Property damage -Sum).Sum)
$human_kills = ($loss_telemetry | Where-Object { $_._T -eq 'LOGPLAYERKILLV2' -and $_.killer.name -eq $player_name -and $_.victim.accountId -notlike "ai.*" }).count
} catch {
$errorMessage = $_.Exception.Message
Write-Warning ("Error processing telemetry stats for {0} in loss {1}: {2}" -f $player_name, $lossid, $errorMessage)
}
}
# # Calculate stats (similar to win stats calculation)
# $human_dmg = "N/A"
# $human_kills = "N/A"
# if ($null -ne $loss_telemetry) {
# try {
# $human_dmg = [math]::Round(($loss_telemetry | Where-Object { $_._T -eq 'LOGPLAYERTAKEDAMAGE' -and $_.attacker.name -eq $player_name -and $_.victim.accountId -notlike "ai.*" -and $_.victim.teamId -ne $_.attacker.teamId } | Measure-Object -Property damage -Sum).Sum)
# $human_kills = ($loss_telemetry | Where-Object { $_._T -eq 'LOGPLAYERKILLV2' -and $_.killer.name -eq $player_name -and $_.victim.accountId -notlike "ai.*" }).count
# } catch {
# $errorMessage = $_.Exception.Message
# Write-Warning ("Error processing telemetry stats for {0} in loss {1}: {2}" -f $player_name, $lossid, $errorMessage)
# }
# }
$loss_stats_table += [PSCustomObject]@{
Name = $player_name
'Human dmg' = "$human_dmg"
'Human Kills' = "$human_kills"
'Dmg' = "$([math]::Round($detailed_player_stats.damageDealt))"
'Kills' = "$($detailed_player_stats.kills)"
'alive' = "$([math]::Round(($detailed_player_stats.timeSurvived / 60)))"
}
# $loss_stats_table += [PSCustomObject]@{
# Name = $player_name
# 'Human dmg' = "$human_dmg"
# 'Human Kills' = "$human_kills"
# 'Dmg' = "$([math]::Round($detailed_player_stats.damageDealt))"
# 'Kills' = "$($detailed_player_stats.kills)"
# 'alive' = "$([math]::Round(($detailed_player_stats.timeSurvived / 60)))"
# }
# Calculate team damage
if ($null -ne $loss_telemetry) {
try {
$teamdmg = $loss_telemetry | Where-Object {
$_._T -eq 'LOGPLAYERTAKEDAMAGE' -and
$_.victim.teamId -eq $_.attacker.teamId -and
$_.victim.accountId -notlike "ai.*" -and
$_.victim.name -ne $_.attacker.name -and
$_.attacker.name -eq $player_name
}
if ($teamdmg.count -ge 1) {
foreach ($victim_name in ($teamdmg.victim.name | Select-Object -Unique)) {
$loss_victims += [PSCustomObject]@{
attacker = $player_name
victim = $victim_name
Damage = "$([math]::Round((($teamdmg | Where-Object { $_.victim.name -eq $victim_name }).damage | Measure-Object -Sum).Sum))"
}
}
}
} catch {
$errorMessage = $_.Exception.Message
Write-Warning ("Error processing team damage for {0} in loss {1}: {2}" -f $player_name, $lossid, $errorMessage)
}
}
}
# # Calculate team damage
# if ($null -ne $loss_telemetry) {
# try {
# $teamdmg = $loss_telemetry | Where-Object {
# $_._T -eq 'LOGPLAYERTAKEDAMAGE' -and
# $_.victim.teamId -eq $_.attacker.teamId -and
# $_.victim.accountId -notlike "ai.*" -and
# $_.victim.name -ne $_.attacker.name -and
# $_.attacker.name -eq $player_name
# }
# if ($teamdmg.count -ge 1) {
# foreach ($victim_name in ($teamdmg.victim.name | Select-Object -Unique)) {
# $loss_victims += [PSCustomObject]@{
# attacker = $player_name
# victim = $victim_name
# Damage = "$([math]::Round((($teamdmg | Where-Object { $_.victim.name -eq $victim_name }).damage | Measure-Object -Sum).Sum))"
# }
# }
# }
# } catch {
# $errorMessage = $_.Exception.Message
# Write-Warning ("Error processing team damage for {0} in loss {1}: {2}" -f $player_name, $lossid, $errorMessage)
# }
# }
# }
# Format the stats table
$content_lossstats = ""
if ($loss_stats_table.Count -gt 0) {
$content_lossstats = '```' + ($loss_stats_table | Format-Table -AutoSize | Out-String) + '```'
}
# # Format the stats table
# $content_lossstats = ""
# if ($loss_stats_table.Count -gt 0) {
# $content_lossstats = '```' + ($loss_stats_table | Format-Table -AutoSize | Out-String) + '```'
# }
# Format team damage table
$content_loss_victims = ""
if ($loss_victims.Count -gt 0) {
$content_loss_victims = ":skull::skull: Team Damage :skull::skull:`n" + '```' + ($loss_victims | Format-Table -AutoSize | Out-String) + '```'
}
# # Format team damage table
# $content_loss_victims = ""
# if ($loss_victims.Count -gt 0) {
# $content_loss_victims = ":skull::skull: Team Damage :skull::skull:`n" + '```' + ($loss_victims | Format-Table -AutoSize | Out-String) + '```'
# }
# Original message construction variables
$losers = $lossmatch[0].stats.name -join ', ' # Join names for display
$map = $map_map[$lossmatch[0].mapName]
$place = ($lossmatch[0].stats | Select-Object -First 1).winPlace # Get placement from the first player stat
$first_player_name = ($lossmatch[0].stats | Select-Object -First 1).name
$replay_url = $lossmatch[0].telemetry_url -replace 'https://telemetry-cdn.pubg.com/bluehole-pubg', 'https://chickendinner.gg'
$replay_url = $replay_url -replace '-telemetry.json', ''
$replay_url = $replay_url + "?follow=$first_player_name" # Follow the first player
$match_settings = @"
``````
match mode $($lossmatch[0].gameMode)
match type $($lossmatch[0].matchType)
map $($map_map[$lossmatch[0].mapName])
id $($lossmatch[0].id)
``````
"@
send-discord-losers -content "We hebben een LOSERT! Geen Kip voor jou! :skull::skull:"
send-discord-losers -content ":partying_face::partying_face::partying_face: Helaas, $($losers) :partying_face::partying_face::partying_face:"
send-discord-losers -content $match_settings
send-discord-losers -content $content_lossstats
send-discord-losers -content $content_loss_victims
send-discord-losers -content "[2D replay](<$replay_url>)"
send-discord-losers -content "Meer match details [DTCH_STATS](<https://dtch.online/matchinfo.php?matchid=$($lossmatch[0].id)>)"
}
# # Original message construction variables
# $losers = $lossmatch[0].stats.name -join ', ' # Join names for display
# $map = $map_map[$lossmatch[0].mapName]
# $place = ($lossmatch[0].stats | Select-Object -First 1).winPlace # Get placement from the first player stat
# $first_player_name = ($lossmatch[0].stats | Select-Object -First 1).name
# $replay_url = $lossmatch[0].telemetry_url -replace 'https://telemetry-cdn.pubg.com/bluehole-pubg', 'https://chickendinner.gg'
# $replay_url = $replay_url -replace '-telemetry.json', ''
# $replay_url = $replay_url + "?follow=$first_player_name" # Follow the first player
# $match_settings = @"
# ``````
# match mode $($lossmatch[0].gameMode)
# match type $($lossmatch[0].matchType)
# map $($map_map[$lossmatch[0].mapName])
# id $($lossmatch[0].id)
# ``````
# "@
# send-discord-losers -content "We hebben een LOSERT! Geen Kip voor jou! :skull::skull:"
# send-discord-losers -content ":partying_face::partying_face::partying_face: Helaas, $($losers) :partying_face::partying_face::partying_face:"
# send-discord-losers -content $match_settings
# send-discord-losers -content $content_lossstats
# send-discord-losers -content $content_loss_victims
# send-discord-losers -content "[2D replay](<$replay_url>)"
# send-discord-losers -content "Meer match details [DTCH_STATS](<https://dtch.online/matchinfo.php?matchid=$($lossmatch[0].id)>)"
# }
foreach ($winid in $new_win_matches) {
@ -237,13 +245,20 @@ foreach ($winid in $new_win_matches) {
$winmatches = $player_matches.player_matches | Where-Object { $_.id -eq $winid }
$telemetry = (invoke-webrequest @($winmatches.telemetry_url)[0]).content | convertfrom-json | where-object { ($_._T -eq 'LOGPLAYERTAKEDAMAGE') -or ($_._T -eq 'LOGPLAYERKILLV2') }
$winners = @(($winmatches | where-object { $_.stats.winPlace -eq 1 }).stats.name)
$2D_replay_url = @($winmatches.telemetry_url)[0] -replace 'https://telemetry-cdn.pubg.com/bluehole-pubg', 'https://chickendinner.gg'
$2D_replay_url = $2D_replay_url -replace '-telemetry.json', ''
$2D_replay_url = $2D_replay_url + "?follow=$($winners[0])"
# $2D_replay_url = @($winmatches.telemetry_url)[0] -replace 'https://telemetry-cdn.pubg.com/bluehole-pubg', 'https://chickendinner.gg'
# $2D_replay_url = $2D_replay_url -replace '-telemetry.json', ''
# $2D_replay_url = $2D_replay_url + "?follow=$($winners[0])"
$2D_replay_url = 'https://chickendinner.gg/' + $winid
$match_stats = Invoke-RestMethod -Uri "https://api.pubg.com/shards/steam/matches/$winid" -Method GET -Headers $headers
if ($winmatches[0].gameMode -eq 'tdm' ) {
continue
}
if (
($winmatches[0].matchtype -eq 'event' -and $winmatches[0].gameMode -ne 'ibr') -or
($winmatches[0].gameMode -eq 'tdm')
) {
Write-Output 'Skipping because of event or tdm'
continue
} #skip tdm matches
if ($winmatches[0].matchType -eq 'custom') {
$players_to_report = $match_stats.included.attributes.stats | where-object { $_.playerId -notlike "ai.*" }
@ -251,11 +266,15 @@ foreach ($winid in $new_win_matches) {
else {
$players_to_report = $match_stats.included.attributes.stats | where-object { $_.winplace -eq 1 }
}
$2D_replay_url = 'https://chickendinner.gg/' + $winid + "/" + $players_to_report[0].name
if ($new_win_matches.count -le 10) {
#fail safe
$winnerswithurl = @()
foreach ($winner in $winners) {
$winnerswithurl += "[$winner](<https://dtch.online/latestmatches.php?selected_player=$($winner)>)"
}
send-discord -content ":chicken: :chicken: **WINNER WINNER CHICKEN DINNER!!** :chicken: :chicken:"
send-discord -content ":partying_face::partying_face::partying_face: Gefeliciteerd $($winners -join ', ') :partying_face::partying_face::partying_face:"
send-discord -content ":partying_face::partying_face::partying_face: Gefeliciteerd $($winnerswithurl -join ', ') :partying_face::partying_face::partying_face:"
$match_settings = @"
``````
match mode $($winmatches[0].gameMode)
@ -336,6 +355,8 @@ k_t = Team eliminaties
foreach ($item in $player_matches) {
if ($item.PSObject.Properties.Name -contains "new_win_matches") {
$item.new_win_matches = $null
}
if ($item.PSObject.Properties.Name -contains "new_loss_matches") {
$item.new_loss_matches = $null
}
}
@ -348,3 +369,4 @@ $newJson | out-file "$scriptroot/../data/player_matches.json"
remove-lock
Stop-Transcript

View file

@ -4,9 +4,11 @@ import discord
import random
import asyncio
import re
from textwrap import dedent
from discord.ext import commands
from openai import OpenAI
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
def get_token():
with open("config.php", "r") as file:
content = file.read()
@ -29,10 +31,13 @@ intents.presences = True # Nodig als de bot presences moet zien
intents.members = True # Nodig om leden in een voice channel te zien
bot = commands.Bot(command_prefix="!", intents=intents)
client = OpenAI(api_key=OPENAI_API_KEY)
@bot.event
async def on_ready():
print(f'Bot is ingelogd als {bot.user}')
channel = bot.get_channel(759006368832159745)
if channel:
await channel.send("Ben er weer!")
@bot.command()
async def test(ctx):
@ -125,19 +130,19 @@ async def teamify(ctx, *args):
await ctx.send(f"Kanaal {channel.name} is opgeruimd omdat het leeg was!")
@bot.command()
async def whoisbest(ctx, category="Casual", matchesback=18):
async def whoisbest(ctx, category="Casual", matchesback=18, top=3):
if category.lower() == "help":
help_message = (
"**Gebruik van het commando `whoisbest`:**\n"
"`!whoisbest [category] [matchesback]`\n\n"
"`!whoisbest [category] [matchesback] [top]`\n\n"
"**Parameters:**\n"
"`category` - De categorie van de stats, bijv. 'Casual' of 'Ranked'. Niet hoofdlettergevoelig.\n"
"`matchesback` - Het minimum aantal matches dat een speler gespeeld moet hebben om mee te tellen (standaard 18).\n\n"
"**Voorbeeld:**\n"
"`!whoisbest Casual 18`\n"
"Laat de top 3 spelers zien op basis van winratio en gemiddelde damage in de Casual categorie met minimaal 18 matches.\n\n"
"Laat de top 3 spelers zien op basis van winratio en gemiddelde damage in de Casual categorie met minimaal 18 matches.\n"
"Typ `!whoisbest help` om deze uitleg opnieuw te zien."
)
await ctx.send(help_message)
@ -173,10 +178,10 @@ async def whoisbest(ctx, category="Casual", matchesback=18):
return
# Sorteer spelers op winratio (aflopend)
top_winratio = sorted(players, key=lambda x: x.get("winratio", 0), reverse=True)[:3]
top_winratio = sorted(players, key=lambda x: x.get("winratio", 0), reverse=True)[:top]
# Sorteer spelers op gemiddelde damage (aflopend)
top_ahd = sorted(players, key=lambda x: x.get("ahd", 0), reverse=True)[:3]
top_ahd = sorted(players, key=lambda x: x.get("ahd", 0), reverse=True)[:top]
# Bouw het bericht op
message = f"**\U0001F3C6 Top 3 Winratio ({actual_category})**\n"
@ -186,11 +191,55 @@ async def whoisbest(ctx, category="Casual", matchesback=18):
message += f"\n**\U0001F480 Top 3 AHD ({actual_category})**\n"
for i, player in enumerate(top_ahd, start=1):
message += f"{i}. **{player['playername']}** - {player['ahd']:.2f}\n"
##AI
await ctx.send(message)
system_prompt = dedent(f"""
Je bent een Discord announcer-bot op de PUBG-server van DTCH.
Stijl: brutaal/competitief, licht denigrerend maar leesbaar.
AHD = Average Human Damage
Regels:
- Gebruik uitsluitend de meegeleverde stats-tekst.
- Output ALLEEN Discord-markdown (geen JSON, geen codeblokken).
- Structuur:
1) Titel met category en korte snedige ondertitel.
2) **🏆 Top {top} Winratio** en **💀 Top {top} AHD** (exact die koppen).
3) Per regel: 🥇/🥈/🥉 + **naam** + waarde (winratio met %).
4) De rest van de regels doe je zonder medaille gewoon een cijfer
5) Sluit af met 1 of 2 regels analyse van de stats, gebruik humor.
- Opgegeven parameters:
Categorie: {category}
Minimaal aantal matches: {matchesback}
Top: {top}
- verdere info
1) Als de aantal matches laag is (onder de 15) dan zijn cijfers niet echt meer representatief. Meld dat dan ook.
- Max ~1800 tekens.
""").strip()
user_prompt = dedent(f"""
Verpak onderstaande stats-tekst in één strakke Discord-post volgens de regels.
Wijzig geen waardes, haal alles uit de tekst tussen START/EINDE.
[STATS-TEKST START]
{message}
[STATS-TEKST EINDE]
""").strip()
response = client.chat.completions.create(
model="gpt-5-nano",
#temperature=0.6,
#presence_penalty=0.2,
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt},
],
)
antwoord = response.choices[0].message.content
await ctx.send(f"{ctx.author.mention} {antwoord[:1900]}")
except Exception as e:
await ctx.send(f"Fout bij het laden van de statistieken: {str(e)}")
await ctx.send(f"{ctx.author.mention} Er ging iets mis: {e}")
##AIEND
@bot.event
async def on_voice_state_update(member, before, after):
@ -215,7 +264,15 @@ async def on_voice_state_update(member, before, after):
async def on_member_join(member):
logging_channel = discord.utils.get(member.guild.text_channels, name="raadhuisplein")
if logging_channel:
await logging_channel.send(f"🎉 Welkom {member.mention} op de server! We hopen dat je een leuke tijd hebt!")
welcome_message = (
f"🎉 Welcome {member.mention} to **{member.guild.name}**!\n\n"
"👋 We're glad to have you here.\n"
"👉 Want to jump right in? Type `!iamgamer` in the chat and you'll get the **Tourists** role.\n"
"With that role you can join the fun and games with everyone else. 🎮\n"
"Use !dtch_help for more info\n\n"
"Enjoy your stay and have a great time! 🚀"
)
await logging_channel.send(welcome_message)
@bot.event
async def on_member_remove(member):
@ -251,5 +308,203 @@ async def moveall(ctx):
await ctx.send(f"{moved_members} speler(s) zijn verplaatst naar het teamify kanaal.")
else:
await ctx.send("Er waren geen spelers om te verplaatsen.")
@bot.command()
async def iamgamer(ctx):
role = discord.utils.get(ctx.guild.roles, name="Tourists")
if role is None:
await ctx.send("De rol **Tourists** bestaat niet!")
return
try:
await ctx.author.add_roles(role)
await ctx.send(f"{ctx.author.mention}, je bent nu een **Tourist**! Veel plezier! 🎮")
except Exception as e:
await ctx.send(f"Er is iets misgegaan bij het toekennen van de rol: {e}")
@bot.command(name="dtch_help", aliases=["commands"])
async def dtch_help_command(ctx):
embed = discord.Embed(
title="📖 DTCH Bot Command Help",
description="Heres a list of all available commands and how to use them:",
color=discord.Color.blue()
)
embed.add_field(
name="👉 !teamify",
value=(
"`!teamify` - Split players into random teams of max 4.\n"
"`!teamify <number_of_teams>` - Split players into a given number of teams.\n"
"`!teamify <number_of_teams> move` - Split & move players into temporary voice channels.\n"
"`!teamify move` - Auto split & move players.\n"
"🔹 Works only in the **#teamify** channel."
),
inline=False
)
embed.add_field(
name="👉 !moveall",
value="`!moveall` - Moves all players from other voice channels into the **teamify** channel.",
inline=False
)
embed.add_field(
name="👉 !whoisbest",
value=(
"`!whoisbest [category] [matchesback]`\n"
"Shows the top 3 players based on win ratio and average damage.\n"
"`category` = e.g. Casual, Ranked\n"
"`matchesback` = minimum matches required (default: 18)\n"
"Example: `!whoisbest Casual 18`"
),
inline=False
)
embed.add_field(
name="👉 !iamgamer",
value="`!iamgamer` - Gives you the **Tourists** role 🎮 so you can join games and unlock more fun.",
inline=False
)
embed.set_footer(text="✨ For advanced options, use: !teamify help or !whoisbest help")
await ctx.send(embed=embed)
@bot.command()
@commands.cooldown(1, 15, commands.BucketType.user)
async def ask(ctx, *, vraag: str):
## CLAN MEMBERS
file_path = os.path.join("..", "config", "clanmembers.json")
# Inlezen als string
with open(file_path, "r", encoding="utf-8") as f:
clanmembers_str = f.read()
#LIFETIME STATS
file_path_lifetimestats = os.path.join("..", "data", "player_lifetime_data.json")
with open(file_path_lifetimestats, "r", encoding="utf-8") as file:
data_lifetimestats = json.load(file)
squad_str = json.dumps(data_lifetimestats.get("squad", {}), indent=2)
#Last stats
file_path_laststats = os.path.join("..", "data", "player_last_stats.json")
with open(file_path_laststats, "r", encoding="utf-8") as file:
data_laststat = json.load(file)
casual_str = json.dumps(data_laststat.get("Casual", []), indent=2)
ranked_str = json.dumps(data_laststat.get("Ranked", []), indent=2)
custom_str = json.dumps(data_laststat.get("custom", []), indent=2)
# Online members
voice_members = [
member.display_name
for vc in ctx.guild.voice_channels
for member in vc.members
]
voice_str = ", ".join(voice_members) if voice_members else "Niemand zit in een voice kanaal"
"""Stuur een vraag naar OpenAI"""
try:
async with ctx.typing():
response = client.chat.completions.create(
model="gpt-5-nano",
messages=[
{
"role": "system",
"content": (
"Je bent een licht denigrerende chatbot in Discord, actief op de PUBG server van clan DTCH. "
f"De vraag is gesteld door {ctx.author.display_name}. "
# Context
f"Clanleden: {clanmembers_str}. "
f"Momenteel in voice: {voice_str}. "
f"Lifetime stats (squad): {squad_str}. "
f"Casual (spelen we toch wel het vaakst met elkaar, belangrijke stat dus) stats: {casual_str}. "
f"Ranked stats: {ranked_str}. "
f"Custom stats (clan games meestal tegen elkaar): {custom_str}. "
# Richtlijnen voor antwoord
"Houd je antwoorden kort en bondig, met maximaal 1600 tekens. "
"Kill Death Human (KD_H) en winrato zijn de belangrijkste stats omdat bots heel makkelijk te killen zijn vinden de Human Kill death het belangrijkste"
"Gebruik Discord markdown (``` of **vetgedrukt**) wanneer je stats of tabellen toont. "
"Wees een beetje sarcastisch, maar wel begrijpelijk. "
"Stel geen vragen want je hebt geen context bij de volgende prompt."
)
},
{"role": "user", "content": vraag},
],
)
antwoord = response.choices[0].message.content
await ctx.send(f"{ctx.author.mention} {antwoord[:1900]}")
except Exception as e:
await ctx.send(f"{ctx.author.mention} Er ging iets mis: {e}")
@ask.error
async def ask_error(ctx, error):
if isinstance(error, commands.CommandOnCooldown):
retry_after = int(error.retry_after + 0.999)
await ctx.reply(f"Rustig {ctx.author.display_name}, probeer het over {retry_after}s nog eens.")
else:
raise error
@bot.command()
async def loterij(ctx, *members: discord.Member):
"""
Gebruik:
!loterij @naam1 @naam2 @naam3
"""
# Alleen in #teamify? -> uncomment als je dat ook wilt
# if ctx.channel.name != "teamify":
# await ctx.send("Dit commando kan alleen worden gebruikt in het #teamify kanaal.")
# return
if not members or len(members) < 2:
await ctx.send("Gebruik: `!loterij @naam1 @naam2 ...` (minimaal 2 mensen, anders is het wel héél zielig).")
return
# Uniek maken (als iemand 2x getagd wordt telt 'ie maar 1x mee)
unique_members = []
seen_ids = set()
for m in members:
if m.id not in seen_ids:
unique_members.append(m)
seen_ids.add(m.id)
# Tekst “tussen A, B en C” netjes bouwen
mentions = [m.mention for m in unique_members]
if len(mentions) == 2:
between_text = f"{mentions[0]} en {mentions[1]}"
else:
between_text = f"{', '.join(mentions[:-1])} en {mentions[-1]}"
winnaar = random.choice(unique_members)
await ctx.send(f"En de loterij gaat tussen {between_text}.")
# Countdown
await asyncio.sleep(1)
await ctx.send("in 3")
await asyncio.sleep(1)
await ctx.send("2")
await asyncio.sleep(1)
await ctx.send("1")
await asyncio.sleep(1)
await ctx.send("trom gerofel 🥁")
await asyncio.sleep(1)
await ctx.send(f"De winnaar is {winnaar.mention} 🎆🎇")
@loterij.error
async def loterij_error(ctx, error):
if isinstance(error, commands.BadArgument):
await ctx.send(
"Ik snap er niks van 🤨\n"
"Gebruik het zo:\n"
"`!loterij @naam1 @naam2 @naam3`\n"
"Zorg dat je **echte Discord-mentions** gebruikt."
)
else:
raise error
bot.run(token)

View file

@ -13,6 +13,7 @@ if ($host == 'dev.dtch.online') {
<a href="latestmatches.php">Last Matches</a>
<a href="topstats.php">Top20</a>
<a href="user_stats.php">User Stats</a>
<a href="videos.php">Videos</a>
</div>
<a href="javascript:void(0);" class="icon" onclick="myFunction()">
<i class="fa fa-bars"></i>

View file

@ -240,3 +240,87 @@ td, th {
background-color: #0f0f0f;
color: #e69109;
}
/* Videos page styles */
.videos-container {
display: flex;
flex-wrap: wrap;
gap: 16px;
justify-content: center;
padding: 1rem;
}
.video-item {
flex: 1 1 300px;
max-width: 100%;
}
.video-item video {
max-width: 100%;
max-height: 80vh;
width: auto;
height: auto;
object-fit: contain;
display: block;
margin: 0 auto;
}
/* Share and theatre button styles */
.video-controls {
display: flex;
justify-content: center;
align-items: center;
margin-top: 0.5rem;
gap: 0.5rem;
}
/* Theatre mode styles */
.video-item.theatre-mode {
flex: 1 1 100%;
max-width: 100%;
}
.video-item.theatre-mode video {
width: 100%;
height: auto;
max-height: none;
}
.video-title {
text-align: center;
font-size: 1.2em;
font-weight: bold;
margin-top: 10px;
margin-bottom: 10px;
}
.video-item.theatre-mode {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.9);
z-index: 1000;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 20px;
box-sizing: border-box;
}
.video-item.theatre-mode video {
max-width: 90%;
max-height: 80vh;
width: auto;
height: auto;
}
.video-item.theatre-mode .video-title {
color: #fff;
order: -1; /* Display title above the video */
}
.video-item.theatre-mode .video-controls {
position: relative;
bottom: auto;
margin-top: 15px;
}

View file

@ -5,6 +5,16 @@ table {
td, th {
padding: 8px;
}
/* Theatre mode mobile styles */
.video-item.theatre-mode {
flex: 1 1 100%;
max-width: 100%;
}
.video-item.theatre-mode video {
width: 100%;
height: auto;
max-height: none;
}
.topnav {
overflow: hidden;
@ -82,3 +92,49 @@ section h2 {
margin-top: 10px;
}
/* Videos page responsive adjustments */
.videos-container {
display: flex;
flex-wrap: wrap;
gap: 16px;
justify-content: center;
padding: 1rem;
}
.video-item {
flex: 1 1 100%;
max-width: 100%;
}
.video-item video {
width: 100%;
max-width: 100%;
height: auto;
display: block;
margin: 0 auto;
}
/* Share and theatre button mobile styles */
.video-controls {
display: flex;
justify-content: center;
align-items: center;
margin-top: 0.5rem;
gap: 0.5rem;
}
.video-title {
text-align: center;
font-size: 1.1em;
font-weight: bold;
margin-top: 8px;
margin-bottom: 8px;
}
.video-item.theatre-mode {
padding: 10px;
}
.video-item.theatre-mode video {
max-width: 100%;
max-height: 70vh;
}
.video-item.theatre-mode .video-controls {
margin-top: 10px;
}

View file

@ -157,15 +157,15 @@ $lastMatches = array_slice($allMatches, 0, 8);
if (substr($playerStats['playerId'], 0, 2) !== 'ai') {
// Create links for each stat
echo "<tr>";
echo "<td><a href='https://pubg.op.gg/user/" . urlencode($playerStats['name']) . "' target='_blank'>" . htmlspecialchars($playerStats['name']) . "</a></td>";
echo "<td><a href='https://pubg.op.gg/user/" . urlencode($playerStats['name']) . "' target='_blank'> Human </a></td>";
echo "<td><a href='https://pubg.op.gg/user/" . urlencode($playerStats['name']) . "' target='_blank'>" . htmlspecialchars($playerStats['kills']) . "</a></td>";
echo "<td><a href='https://pubg.op.gg/user/" . urlencode($playerStats['name']) . "' target='_blank'>" . htmlspecialchars($playerStats['HumanDmg']) . "</a></td>";
echo "<td><a href='https://pubg.op.gg/user/" . urlencode($playerStats['name']) . "' target='_blank'>" . htmlspecialchars($playerStats['timeSurvived']) . "</a></td>";
echo "<td><a href='https://pubg.op.gg/user/" . urlencode($playerStats['name']) . "' target='_blank'>" . htmlspecialchars($playerStats['winPlace']) . "</a></td>";
echo "<td><a href='https://pubg.op.gg/user/" . urlencode($playerStats['name']) . "' target='_blank'>" . htmlspecialchars($playerStats['revives']) . "</a></td>";
echo "<td><a href='https://pubg.op.gg/user/" . urlencode($playerStats['name']) . "' target='_blank'>" . htmlspecialchars($playerStats['DBNOs']) . "</a></td>";
echo "<td><a href='https://pubg.op.gg/user/" . urlencode($playerStats['name']) . "' target='_blank'>" . htmlspecialchars($playerStats['assists']) . "</a></td>";
echo "<td><a href='https://www.pubg-meta.com/player-stats/steam/" . urlencode($playerStats['name']) . "' target='_blank'>" . htmlspecialchars($playerStats['name']) . "</a></td>";
echo "<td><a href='https://www.pubg-meta.com/player-stats/steam/" . urlencode($playerStats['name']) . "' target='_blank'> Human </a></td>";
echo "<td><a href='https://www.pubg-meta.com/player-stats/steam/" . urlencode($playerStats['name']) . "' target='_blank'>" . htmlspecialchars($playerStats['kills']) . "</a></td>";
echo "<td><a href='https://www.pubg-meta.com/player-stats/steam/" . urlencode($playerStats['name']) . "' target='_blank'>" . htmlspecialchars($playerStats['HumanDmg']) . "</a></td>";
echo "<td><a href='https://www.pubg-meta.com/player-stats/steam/" . urlencode($playerStats['name']) . "' target='_blank'>" . htmlspecialchars($playerStats['timeSurvived']) . "</a></td>";
echo "<td><a href='https://www.pubg-meta.com/player-stats/steam/" . urlencode($playerStats['name']) . "' target='_blank'>" . htmlspecialchars($playerStats['winPlace']) . "</a></td>";
echo "<td><a href='https://www.pubg-meta.com/player-stats/steam/" . urlencode($playerStats['name']) . "' target='_blank'>" . htmlspecialchars($playerStats['revives']) . "</a></td>";
echo "<td><a href='https://www.pubg-meta.com/player-stats/steam/" . urlencode($playerStats['name']) . "' target='_blank'>" . htmlspecialchars($playerStats['DBNOs']) . "</a></td>";
echo "<td><a href='https://www.pubg-meta.com/player-stats/steam/" . urlencode($playerStats['name']) . "' target='_blank'>" . htmlspecialchars($playerStats['assists']) . "</a></td>";
echo "</tr>";
} else {
// Display without link

View file

@ -48,7 +48,13 @@ foreach ($player in $player_data) {
$stats.included = $sortedStats
$stats | ConvertTo-Json -Depth 100 | Out-File "$scriptroot/../data/matches/$match.json"
}
if (
($stats.data.attributes.matchtype -eq 'event' -and $stats.data.attributes.gameMode -ne 'ibr') -or
($stats.data.attributes.gameMode -eq 'tdm')
) {
Write-Output 'Skipping because of event or tdm'
continue
}
$playermatches += [PSCustomObject]@{
stats = $stats.included.ATTRIBUTES.stats | where-object { $_.name -eq $player.attributes.name }
matchType = $stats.data.attributes.matchtype

View file

@ -161,6 +161,14 @@ $groupedGuids_clan_matches_gt_3 = $guids | Group-Object | Where-Object { $_.Coun
$last_month = (get-date).AddMonths($monthsback)
foreach ($file in $matchfiles) {
$json = get-content $file | ConvertFrom-Json
if (
($stats.data.attributes.matchtype -eq 'event' -and $stats.data.attributes.gameMode -ne 'ibr') -or
($stats.data.attributes.gameMode -eq 'tdm')
) {
Write-Output 'Skipping because of event or tdm'
continue
}
if ($json.created -gt $last_month) {
$killstats += $json
if ($groupedGuids_clan_matches_gt_1.Name -contains $json.matchid) {

102
videos.php Normal file
View file

@ -0,0 +1,102 @@
<?php
$ogDescription = "Bekijk alle video's";
// Scan the media/videos directory for mp4 files
$videosDir = __DIR__ . '/media/videos';
$allFiles = scandir($videosDir);
$videoFiles = array_filter($allFiles, function($file) use ($videosDir) {
return is_file($videosDir . '/' . $file) && strtolower(pathinfo($file, PATHINFO_EXTENSION)) === 'mp4';
});
// Build array with creation time and sort by creation date descending
$videoData = [];
foreach ($videoFiles as $file) {
$path = $videosDir . '/' . $file;
$videoData[] = [
'filename' => $file,
'ctime' => filectime($path)
];
}
usort($videoData, function($a, $b) {
return $b['ctime'] - $a['ctime'];
});
?>
<!DOCTYPE html>
<html lang="en">
<?php include './includes/head.php'; ?>
<body>
<?php include './includes/navigation.php'; ?>
<?php include './includes/header.php'; ?>
<main>
<section>
<h2>Videos</h2>
<?php if (!empty($videoData)): ?>
<div class="videos-container">
<?php foreach ($videoData as $video): ?>
<div class="video-item">
<video controls>
<source src="media/videos/<?php echo htmlspecialchars($video['filename']); ?>" type="video/mp4">
Your browser does not support the video tag.
</video>
<p class="video-title"><?php echo pathinfo($video['filename'], PATHINFO_FILENAME); ?></p>
<div class="video-controls">
<button class="btn share-btn">Delen</button>
<button class="btn theatre-btn">Theatermodus</button>
</div>
</div>
<?php endforeach; ?>
</div>
<?php else: ?>
<p>No videos found.</p>
<?php endif; ?>
</section>
</main>
<?php include './includes/footer.php'; ?>
<script>
document.addEventListener('DOMContentLoaded', function() {
document.querySelectorAll('.share-btn').forEach(function(btn) {
btn.addEventListener('click', function() {
var videoItem = btn.closest('.video-item');
var src = videoItem.querySelector('video source').src;
if (navigator.share) {
navigator.share({ title: videoItem.querySelector('p').innerText, url: src })
.catch(function(error) { console.error('Error sharing', error); });
} else if (navigator.clipboard) {
navigator.clipboard.writeText(src).then(function() {
alert('Videolink gekopieerd naar klembord');
}, function(err) {
alert('Kon link niet kopiëren: ' + err);
});
} else {
prompt('Kopieer deze link:', src);
}
});
});
document.querySelectorAll('.theatre-btn').forEach(function(btn) {
btn.addEventListener('click', function() {
var clickedVideoItem = btn.closest('.video-item');
// Remove theatre mode from all other videos
document.querySelectorAll('.video-item.theatre-mode').forEach(function(item) {
if (item !== clickedVideoItem) {
item.classList.remove('theatre-mode');
item.querySelector('.theatre-btn').innerText = 'Theatermodus';
}
});
// Toggle theatre mode for the clicked video
var isActive = clickedVideoItem.classList.toggle('theatre-mode');
btn.innerText = isActive ? 'Sluit theatermodus' : 'Theatermodus';
});
});
});
</script>
</body>
</html>