package ONO::ToolBox::Chat;
################################################################################
# COPYRIGHT / LICENSE #
################################################################################
#
# This file is part of the ONO Software Project.
#
# Copyright (C) 2000-2025 Jos KIRPS [ www.kirps.com | jos_AT_kirps_DOT_com ]
# and The Joopita Project [ www.joopita.org | contact_AT_joopita_DOT_com ]
#
# This file, as well as other parts of the ONO Software Project or related
# elements, are FREE SOFTWARE available under the ARTISTIC LICENSE 2.0.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# For the full license, see /ono/osr/license/LICENSE.txt, or write to
# jos_AT_kirps_DOT_com or contact_AT_joopita_DOT_com.
#
################################################################################
# END OF COPYRIGHT / LICENSE, HERE COMES THE CODE ... #
################################################################################
use strict;
use ONO::IO;
use ONO::DB;
use ONO::Render;
use ONO::FW::User::Init;
use ONO::FW::User::ToolBox;
use ONO::Lib::Code::RandomID;
use ONO::Lib::Web::Cookie;
use ONO::Lib::DateTime::ToolBox;
use ONO::ToolBox::Auth;
use ONO::ToolBox::Input;
use ONO::ToolBox::Logfile;
###############################################################################
# ONO
###############################################################################
#: This is ONO's built-in chat / messenger box, that may be displayed at the
#: bottom of each page for example, as soon as you are logged in.
#:
#: Note that ONO_FW_User_Screen_Messages offers full-page access to
#: the messenger.
sub chatbox {
#: This generates the chat box in the bottom right corner of the screen,
#: as soon as you are logged in.
my (
$self,
$db,
$community,
$lang,
$vars_ref,
$BASE,
) = @_;
my %vars = %$vars_ref;
if ($vars{'username'}) {
my ($hide1,$hide2) = ('',' hide');
my $URL = "$BASE/ono/osr/images/default/embed/pleasewait/black.html";
my $cookie = ONO::Lib::Web::Cookie->get("ono_chat_box");
if ($cookie && $vars{'community_screen'} ne "messages") {
($hide1,$hide2) = (' hide','');
$URL = "$BASE/cgi-bin/local/perl/$community/chat.pl?lang=$lang";
my @cp = split(/:/,$cookie);
if ($cp[1] && $cp[2]) {
$URL = "$BASE/cgi-bin/local/perl/$community/chat.pl?lang=$lang&mode=$cp[1]&thread=$cp[2]";
}
}
my ($messages_unread,$UPDATES,$ALARM);
if (ONO::IO->sysload(50)) {
my $dir = ONO::FW::User::Init->getuserdir($vars{'username'},$community);
if (!ONO::IO->exists("$dir/blocked-features/messages.txt")) {
foreach my $line (ONO::DB->select($db,"${community}_messages_updates","username = '$vars{'username'}'")) {
my @row = ONO::DB->readcols($line);
$messages_unread = $messages_unread + $row[2];
}
if ($messages_unread) {
$UPDATES = qq~<div class="block24 radius16 abs" style="top:-3px;right:-3px;background-color:#ff3333"></div>
<div class="block24 abs cole bold center sxmall" style="top:-2px;right:-3px">$messages_unread</div>
~;
$ALARM = " alarm_messages";
}
}
}
return qq~<div class="fix" style="bottom:0px;right:20px;width:1px;z-index:99">
<div id="ono_chatbox_min" class="box_black$ALARM fr pad10_0 flat_bottom cursorlink rel$hide1" onmouseover="delay();" onclick="onojs_chatbox_open('$BASE/cgi-bin/local/perl/$community/chat.pl?lang=$lang');">
<table class="default_table mt5 mb5">
<tr>
<td><img class="block32" src="$BASE/ono/osr/images/icons/crystal/64x64/apps/kopete.png" alt=""></td>
<td class="large bold hide800">Chats</td>
</tr>
</table>
$UPDATES
</div>
<div id="ono_chatbox_max" class="abs$hide2" style="bottom:0px;right:0px;width:320px">
<div class="box_black flat_bottom rel">
<iframe id="ono_chatbox_iframe" src="$URL" scrolling="no"
style="border:1px solid #555555;width:298px;height:480px;overflow:hidden"></iframe>
<div class="abs" style="top:17px;right:12px">
<a href="javascript:void(0);" onclick="onojs_chatbox_close('$BASE/cgi-bin/local/perl/$community/chat.pl?lang=$lang&mode=close');">
<img class="block24" src="$BASE/ono/osr/images/icons/crystal/32x32/ono/close.png" alt="">
</a>
</div>
</div>
</div>
</div>
<script>
var onojs_chatbox_delay = function (elem, callback) {
var timeout = null;
elem.onmouseover = function() {timeout = setTimeout(callback, 500);};
elem.onmouseout = function() {clearTimeout(timeout);}
};
onojs_chatbox_delay(document.getElementById('ono_chatbox_min'), function() {
onojs_chatbox_open('$BASE/cgi-bin/local/perl/$community/chat.pl?lang=$lang');
});
</script>
~;
} else {
return "";
}
}
sub chat {
#: This generates the content of the chat box, that will automatically
#: reload on a regular basis.
my (
$self,
$db,
$community,
$BASE,
) = @_;
my ($vars_ref,%vars) = ONO::ToolBox::Input->get();
$vars_ref = ONO::ToolBox::Auth->auth($db,$community,$vars_ref);
%vars = %$vars_ref;
my $CHAT_URL = "$BASE/cgi-bin/local/perl/$community/chat.pl?lang=$vars{'lang'}";
my $CHAT_URL2 = "/cgi-bin/local/perl/$community/chat.pl?lang=$vars{'lang'}";
if (ONO::IO->devstation) {
$vars{'username'} = "jos";
}
my $thread = $vars{'thread'};
$thread =~ s~[^0-9]~~g;
my $ADD;
if ($vars{'mode'} ne "new") {
$ADD = qq~ <td><a href="$CHAT_URL&mode=new"><img class="block24 mr20" src="/ono/osr/images/icons/ono/32x32/add.png" alt=""></a></td>~;
}
my $CHAT = qq~<table class="wide_table mb5">
<tr>
<td><a href="$CHAT_URL"><img class="block32" src="/ono/osr/images/icons/crystal/64x64/apps/kopete.png" alt=""></a></td>
<td class="w100"><div class="cursorlink large bold cole" onclick="window.location='$CHAT_URL2';">Chats</div></td>
$ADD
<td class="pad10_2"></td>
</tr>
</table>
~;
my $dir = ONO::FW::User::Init->getuserdir($vars{'username'},$community);
if (ONO::IO->exists("$dir/blocked-features/messages.txt")) {
ONO::Render->render_pre("","",\%vars);
$CHAT .= qq~<div class="box_fabric">~;
$CHAT .= ONO::FW::User::ToolBox->social_disabled_msg($vars{'lang'});
$CHAT .= qq~</div>~;
} else {
$vars{'cookie_sid'} = ONO::Lib::Web::Cookie->make("ono_chat_box","chat:$vars{'mode'}:$thread","1d",$vars_ref);
if ($vars{'mode'} eq "new") {
$vars{'cookie_sid'} = ONO::Lib::Web::Cookie->make("ono_chat_box","chat::","1d",$vars_ref);
}
if ($vars{'mode'} eq "close") {
$vars{'cookie_sid'} = ONO::Lib::Web::Cookie->make("ono_chat_box","chat:$vars{'mode'}:$thread","expire",$vars_ref);
$CHAT .= ONO::IO->refresh("$BASE/ono/osr/images/default/embed/pleasewait/black.html");
}
ONO::Render->render_pre("","",\%vars);
foreach my $line (ONO::DB->select($db,"${community}_messages_projects","type = 'messages'")) {
my @row = ONO::DB->readcols($line);
if (!$vars{'mode'}) {
$vars{'refresh'}++;
my $refresh_secs = 15+$vars{'refresh'};
$CHAT .= qq~<div class="box_fabric" style="padding:5px 0px 10px 10px">
<div style="height:415px;overflow-y:scroll" onmouseover="onojs_sethtml('timer_chat_reload','20');">
<div id="timer_chat_reload" class="hide">$refresh_secs</div>
<script>onojs_timer_countdown_id_refresh('chat_reload','$CHAT_URL&refresh=$vars{'refresh'}');</script>
~;
my $count;
my $SYSLOAD_OK = ONO::IO->sysload(50);
foreach my $line2 (ONO::DB->select($db,"${community}_messages_pages","project = '$row[0]' AND (pub_owner = '$vars{'username'}' OR pub_group LIKE '%:$vars{'username'}:%')","modification_timestamp DESC")) {
my @row2 = ONO::DB->readcols($line2);
$count++;
my $IMG = ONO::FW::User::Init->profileimage($row2[76],48);
my $TITLE;
if ($row2[3]) {
$TITLE = qq~<div class="bold">$row2[3]</div>~;
}
my $TEXT = $row2[24];
if (ONO::DB->driver eq "odbc") {
eval "use Encode";
if (!$@) {
Encode::from_to($TEXT,'utf-8','latin1');
}
}
$TEXT =~ s~\<(.*?)\>~ ~g;
$TEXT =~ s~ ~ ~g;
$TEXT = ucfirst substr($TEXT,0,200);
my $USERS = $row2[14];
$USERS =~ s~^:~~;
$USERS =~ s~:$~~;
$USERS =~ s~:~, ~g;
if (length $USERS > 50) {
# $USERS = substr($USERS,0,50);
# $USERS =~ s~, (.*?)$~, ...~;
my @up = split(/,/,$USERS);
$USERS = @up;
$USERS .= " users";
}
my $UPDATES;
if ($SYSLOAD_OK) {
foreach my $line3 (ONO::DB->select($db,"${community}_messages_updates","username = '$vars{'username'}' AND page_id = '$row2[0]'")) {
my @row3 = ONO::DB->readcols($line3);
$UPDATES = $UPDATES + $row3[2];
}
if ($UPDATES) {
$UPDATES = qq~<div class="block20 radius10 abs" style="top:-3px;right:-3px;background-color:#ff3333"></div>
<div class="block20 abs cole bold center small" style="top:-3px;right:-3px">$UPDATES</div>
~;
}
}
$CHAT .= qq~ <div class="mt5 mb5 box_paper box_black_hover mr10 cursorlink" onclick="window.location='$CHAT_URL2&mode=chat&thread=$row2[0]';">
<table class="wide_table">
<tr class="vtop">
<td class="p0"><div class="rel">$IMG$UPDATES</div></td>
<td></td>
<td class="w100"><div class="mt2">$TITLE<span class="bold">$row2[76]:</span> <span class="italic">$TEXT</span><div class="col9 lh125">$USERS</div></div></td>
</tr>
</table>
</div>
~;
}
if (!$count) {
$CHAT .= ONO::IO->refresh("$CHAT_URL&mode=empty");
}
$CHAT .= qq~ </div>
</div>
~;
}
if ($vars{'mode'} eq "new" || $vars{'mode'} eq "empty") {
my @txts = (
"You will be leaving this browser screen, unsaved data in the main window may be lost!",
"new conversation",
"cancel",
);
if ($vars{'lang'} eq "de") {
@txts = (
"Du wirst diesen Browser-Schirm verlassen, nicht gespeicherte Daten im Hauptfenster können verloren gehen!",
"neuer Chat",
"abbrechen",
);
}
if ($vars{'lang'} eq "lu") {
@txts = (
"Du wäers dëse Browser-Schierm verloossen, net gespäichert Daten am Haaptfenster kënne verluer goen!",
"neien Chat",
"annuléieren",
);
}
if ($vars{'lang'} eq "fr") {
@txts = (
"Vous allez quitter cet écran de navigateur, les données non enregistrées dans la fenêtre principale risquent d'être perdues!",
"nouvelle discussion",
"annuler",
);
}
my $CANCEL;
if ($vars{'mode'} eq "new") {
$CANCEL = qq~<a href="$CHAT_URL" class="button_yellow">$txts[2]</a>~;
}
$CHAT .= qq~<div class="pad10_2 large center cole mt20 mb20 ">$txts[0]</div>
<div class="inline auto"><a href="/account/?community_screen=messages&option=new_msg" target="_parent" class="button_green button_big mb20">$txts[1]</a></div>
<div class="inline auto">$CANCEL</div>
~;
}
if ($vars{'mode'} eq "chat" && $thread) {
if ($vars{'chat_post_message'}) {
my $ID = ONO::Lib::Code::RandomID->make;
$vars{'chat_post_message'} =~ s~(\n|\r|\t)~~g;
my $TEXT = substr($vars{'chat_post_message'},0,255);
$TEXT =~ s~\'~ ~g;
$TEXT =~ s~ ~ ~g;
my $time = time();
my $SQL = qq~INSERT INTO ${community}_messages_objects
(id_10,page,published,version,serial,type,object_text,creation_username,creation_timestamp,modification_username,modification_timestamp) VALUES
('$ID','$thread','1','0','0','usersays','$TEXT','$vars{'username'}','$time','$vars{'username'}','$time');
~;
ONO::DB->command($db,$SQL,0,1);
ONO::ToolBox::Logfile->log("communication",$vars{'username'},$TEXT,"chat:$thread:$ID");
$TEXT = substr($TEXT,0,200);
my $SQL = qq~UPDATE ${community}_messages_pages SET
object_text = '$TEXT',
modification_username = '$vars{'username'}',
modification_timestamp = '$time'
WHERE id = '$thread';
~;
ONO::DB->command($db,$SQL,0,1);
}
ONO::DB->command($db,"DELETE FROM ${community}_messages_updates WHERE username = '$vars{'username'}' AND page_id = '$thread';");
foreach my $line2 (ONO::DB->select($db,"${community}_messages_pages","id = '$thread' AND project = '$row[0]' AND (pub_owner = '$vars{'username'}' OR pub_group LIKE '%:$vars{'username'}:%')")) {
my @row2 = ONO::DB->readcols($line2);
my $TITLE = "Chat";
if ($row2[3]) {
$TITLE = substr($row2[3],0,20);
}
my ($MSGS,$last_time);
foreach my $line3 (ONO::DB->select($db,"${community}_messages_objects","page = '$row2[0]'","modification_timestamp DESC","LIMIT 100 OFFSET 0")) {
my @row3 = ONO::DB->readcols($line3);
my $IMG = ONO::FW::User::Init->profileimage($row3[76],32);
my $TEXT = $row3[24];
if (ONO::DB->driver eq "odbc") {
eval "use Encode";
if (!$@) {
Encode::from_to($TEXT,'utf-8','latin1');
}
}
$TEXT =~ s~\<(.*?)\>~ ~g;
$TEXT =~ s~ ~ ~g;
my $MSG = qq~<div class="lh125"><div class="bold">$row3[76]</div><div class="dowrap">$TEXT</div></div>~;
my $MR;
if ($vars{'username'} eq $row3[76]) {
$MR = " mr50";
$MSG = qq~ <table class="wide_table">
<tr class="vtop">
<td class="w100"><div class="box_highlight pad10_5">$MSG</div></td>
<td><div class="mt5">$IMG</div></td>
<td class="p5"></td>
</tr>
</table>
~;
} else {
$MR = " mr15";
$MSG = qq~ <table class="wide_table">
<tr class="vtop">
<td><div class="mt5">$IMG</div></td>
<td class="w100"><div class="box_paper pad10_5">$MSG</div></td>
<td class="p5"></td>
</tr>
</table>
~;
}
if (!$MSGS || $row3[77] < $last_time-600) {
$last_time = $row3[77];
$row3[77] = ONO::Lib::DateTime::ToolBox->get($row3[77],"","iz",$vars{'lang'});
$MSG .= qq~<div class="small fr bold col9$MR">$row3[77]</div>~;
}
$MSGS = "$MSG$MSGS";
}
$vars{'refresh'}++;
my $refresh_secs = 15+$vars{'refresh'};
$CHAT .= qq~<div class="box_fabric mb10" style="padding-right:0px" onmouseover="onojs_sethtml('timer_chat_reload','30');">
<div class="bb">
<table class="default_table mb2" style="width:280px">
<tr>
<td class="w100 bold">$TITLE</td>
<td>
<a href="$CHAT_URL">
<img class="block24" src="/ono/osr/images/icons/crystal/32x32/ono/close.png" alt="">
</a>
</td>
</tr>
</table>
</div>
<div id="timer_chat_reload" class="hide">$refresh_secs</div>
<script>onojs_timer_countdown_id_refresh('chat_reload','$CHAT_URL&mode=chat&thread=$vars{'thread'}&refresh=$vars{'refresh'}');</script>
<div id="chatbox" style="height:344px;overflow-y:scroll">
$MSGS
</div>
</div>
<form method="post" action="$ENV{'SCRIPT_NAME'}">
<input type="hidden" name="mode" value="chat">
<input type="hidden" name="thread" value="$thread">
<table class="default_table" style="width:299px" onmouseover="onojs_sethtml('timer_chat_reload','40');">
<tr>
<td class="p0 w100">
<input type="text" id="chat_post_message_id" name="chat_post_message" value="" class="query w100"
onmouseover="onojs_sethtml('timer_chat_reload','40');" onkeyup="onojs_sethtml('timer_chat_reload','9999');">
</td>
<td class="p0"><input type="submit" name="chat_post_button" value=">>" class="button_green button_right"></td>
</tr>
</table>
</form>
<script>
onojs_scrolltobottom('chatbox');
onojs_focus('chat_post_message_id');
</script>
~;
}
}
}
}
$vars{'ono_render_body_style'} = "background-color:#555555";
ONO::Render->render($CHAT,"",\%vars);
}
###############################################################################
# end of script
###############################################################################
1;
__END__