You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

356 lines
11 KiB

<?php
namespace App;
use Movim\ImageSize;
use Awobaz\Compoships\Database\Eloquent\Model;
use Movim\Route;
class Conference extends Model
{
public $incrementing = false;
protected $primaryKey = ['session_id', 'conference'];
protected $fillable = ['conference', 'name', 'nick', 'autojoin', 'pinned', 'space_server', 'space_node'];
protected $with = ['contact', 'mujiPresences'];
public const XMLNS_NOTIFICATIONS = 'urn:xmpp:notification-settings:0';
public const XMLNS_PINNED = 'urn:xmpp:bookmarks-pinning:0';
public const XMLNS_MOVIM_CONFERENCE_CALL = '{https://movim.eu}bookmarks-conference-call';
public const NOTIFICATIONS = [
0 => 'never',
1 => 'on-mention',
2 => 'always'
];
public static function saveMany(array $conferences)
{
return Conference::insert($conferences);
}
public function session()
{
return $this->belongsTo(Session::class);
}
public function presences()
{
return $this->hasMany(Presence::class, ['jid', 'session_id'], ['conference', 'session_id'])
->where('resource', '!=', '')
->where('value', '<', 5)
->orderBy('mucrole')
->orderBy('mucaffiliation')
->orderBy('value')
->orderBy('resource');
}
public function mujiPresences()
{
return $this->presences()->whereNotNull('muji_xml')->orderBy('updated_at', 'asc');
}
public function scopeFromSpace($query, ?bool $from = true)
{
return $from
? $query->whereNotNull('space_server')->whereNotNull('space_node')
: $query->whereNull('space_server')->whereNull('space_node');
}
public function isFromSpace(): bool
{
return $this->space_server != null && $this->space_node != null;
}
public function isConferenceCall(): bool
{
return $this->isFromSpace() && $this->call;
}
public function spaceInfo()
{
return $this->hasOne(Info::class, ['server', 'node'], ['space_server', 'space_node']);
}
public function otherPresences()
{
return $this->presences()->where('mucjid', '!=', function ($query) {
$query->select('user_id')
->from('sessions')
->whereColumn('sessions.id', 'presences.session_id');
});
}
public function quoted()
{
return $this->hasMany(Message::class, 'jidfrom', 'conference')
->where('user_id', function ($query) {
$query->select('user_id')
->from('sessions')
->whereColumn('sessions.id', 'conferences.session_id');
})
->where('type', 'groupchat')
->whereNull('subject')
->where('quoted', true)
->where('seen', false);
}
public function presence()
{
return $this->hasOne(Presence::class, ['jid', 'session_id'], ['conference', 'session_id'])
->where('value', '<', 5)
->where('mucjid', function ($query) {
$query->select('user_id')
->from('sessions')
->whereColumn('sessions.id', 'presences.session_id');
});
}
public function members()
{
return $this->hasMany(Member::class, 'conference', 'conference')
->orderBy('role')
->orderBy('affiliation', 'desc');
}
public function activeMembers()
{
return $this->hasMany(Member::class, 'conference', 'conference')
->where('affiliation', '!=', 'outcast')
->where('affiliation', '!=', 'none')
->orderBy('role')
->orderBy('affiliation', 'desc');
}
public function messages()
{
return $this->hasMany(Message::class, ['jidfrom', 'user_id'], ['conference', 'user_id'])
->where('type', 'groupchat')
->orderBy('published', 'desc');
}
public function unreads()
{
return $this->messages()
->whereNull('subject')
->where('seen', false);
}
public function pictures()
{
return $this->messages()
->where('picture', true)
->where('retracted', false);
}
public function links()
{
return $this->messages()
->whereNotNull('urlid')
->where('picture', false)
->where('retracted', false);
}
public function info()
{
return $this->hasOne(Info::class, 'server', 'conference')
->where(function ($query) {
$query->where('node', function ($query) {
$query->select('node')
->from('presences')
//->where('session_id', me()->session->id)
->whereColumn('jid', 'infos.server')
->where('resource', '')
->take(1);
})
->orWhere('node', '');
})
->whereCategory('conference')
->whereType('text');
}
public function contact()
{
return $this->hasOne(Contact::class, 'id', 'conference');
}
public function set(Session $session, \SimpleXMLElement $item)
{
$this->user_id = $session->user_id;
$this->session_id = $session->id;
$this->conference = (string)$item->attributes()->id;
$this->name = (string)$item->conference->attributes()->name;
$this->nick = (string)$item->conference->nick;
$this->autojoin = filter_var($item->conference->attributes()->autojoin, FILTER_VALIDATE_BOOLEAN);
$this->bookmarkversion = (int)substr((string)$item->conference->attributes()->xmlns, -1, 1);
if ($item->conference->extensions) {
if (
$item->conference->extensions->notify
&& $item->conference->extensions->notify->attributes()->xmlns == self::XMLNS_NOTIFICATIONS
) {
if ($item->conference->extensions->notify->never) {
$this->notify = 0;
}
if ($item->conference->extensions->notify->{'on-mention'}) {
$this->notify = 1;
}
if ($item->conference->extensions->notify->always) {
$this->notify = 2;
}
unset($item->conference->extensions->notify);
// Remove the deprecated extension if present
if ($item->conference->extensions->notifications) {
unset($item->conference->extensions->notifications);
}
} else if ( // Deprecated
$item->conference->extensions->notifications
&& $item->conference->extensions->notifications->attributes()->xmlns == 'xmpp:movim.eu/notifications:0'
) {
$notifications = [
'never' => 0,
'quoted' => 1,
'always' => 2
];
$this->notify = (int)$notifications[(string)$item->conference->extensions->notifications->attributes()->notify];
unset($item->conference->extensions->notifications);
}
if (
$item->conference->extensions->pinned
&& in_array($item->conference->extensions->pinned->attributes()->xmlns, [self::XMLNS_PINNED, 'xmpp:movim.eu/pinned:0'])
) {
$this->pinned = true;
unset($item->conference->extensions->pinned);
}
if (
$item->conference->extensions->{'conference-call'}
&& $item->conference->extensions->{'conference-call'}->attributes()->xmlns == self::XMLNS_MOVIM_CONFERENCE_CALL
) {
$this->call = true;
}
$this->extensions = $item->conference->extensions->asXML();
}
}
public function getNotifKeyAttribute(): string
{
return $this->isFromSpace()
? 'space' . $this->space_server . $this->space_node . '|' . $this->conference
: 'chat|' . $this->conference;
}
public function getRouteAttribute(): string
{
return $this->isFromSpace()
? Route::urlize('space', [$this->space_server, $this->space_node, $this->conference])
: Route::urlize('chat', [$this->conference, 'room']);
}
public function getServerAttribute()
{
return \explodeJid($this->conference)['server'];
}
public function getConnectedAttribute()
{
return isset($this->presence);
}
public function getNotificationKeyAttribute(): string
{
return self::NOTIFICATIONS[$this->notify];
}
public function getSpaceCounterIdAttribute(): string
{
return cleanupId($this->space_server . $this->space_node . '-counter');
}
public function getTitleAttribute()
{
if (!empty($this->name)) {
return $this->name;
}
if ($this->info) {
return $this->info->name;
}
if ($this->isGroupChat() && $this->members()->count() > 0) {
$title = '';
$i = 0;
foreach ($this->members()->take(3)->get() as $member) {
$title .= $member->truename;
if ($i < 2) $title .= ', ';
$i++;
}
if ($this->members()->count() > 3) $title .= '…';
return $title;
}
return $this->conference;
}
public function getSubjectAttribute()
{
$subject = $this->session->user
->messages()
->jid($this->session->user, $this->conference)
->whereNotNull('subject')
->whereNull('body')
->whereNull('thread')
->where('type', 'groupchat')
->orderBy('published', 'desc')
->first();
return $subject ? $subject->subject : null;
}
public function getPicture(ImageSize $size = ImageSize::M): string
{
return $this->contact
? $this->contact->getPicture($size)
: avatarPlaceholder($this->name);
}
// https://docs.modernxmpp.org/client/groupchat/#types-of-chat
public function isGroupChat(): bool
{
if ($this->info) {
return $this->info->mucmembersonly && !$this->info->mucsemianonymous;
}
return false;
}
public function toArray()
{
$now = \Carbon\Carbon::now();
return [
'user_id' => $this->attributes['user_id'] ?? null,
'session_id' => $this->attributes['session_id'] ?? null,
'conference' => $this->attributes['conference'] ?? null,
'space_server' => $this->attributes['space_server'] ?? null,
'space_node' => $this->attributes['space_node'] ?? null,
'name' => $this->attributes['name'] ?? null,
'nick' => $this->attributes['nick'] ?? null,
'autojoin' => $this->attributes['autojoin'] ?? null,
'pinned' => $this->attributes['pinned'] ?? false,
'call' => $this->attributes['call'] ?? false,
'created_at' => $this->attributes['created_at'] ?? $now,
'updated_at' => $this->attributes['updated_at'] ?? $now,
'extensions' => $this->attributes['extensions'] ?? null,
'bookmarkversion' => $this->attributes['bookmarkversion'] ?? 0,
'notify' => $this->attributes['notify'] ?? 1,
];
}
}