Initial Commit
This commit is contained in:
19
README.md
Normal file
19
README.md
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# ChatterBox
|
||||||
|
|
||||||
|
Chatterbox allows users to set up a web interface into their iMessages.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
- Make sure your `/Users/<USERNAME>/Library/Messages/{chat.db,chat.db-wal}` files are all-readable, and the folders above it are all read/execute-able.
|
||||||
|
- Enable Apache and PHP
|
||||||
|
- Set the `CHAT_DB_SRC` and `ADDR_DB_SRC` variables in `chatterbox.php`
|
||||||
|
- Move this all into `/Library/WebServer/Documents` (or test it out with the PHP standalone server)
|
||||||
|
|
||||||
|
## Limitations
|
||||||
|
This is honestly a pretty insecure implementation of a web server, so please use at your own risk
|
||||||
|
- There's no authentication
|
||||||
|
- There's no SSL/encryption
|
||||||
|
- It requires all execute/read permissions on your chat and address book databases
|
||||||
|
|
||||||
|
Additionally, there's no functionality yet to send messages or view attachments. I'm working on that part. AppleScript is just so atrocious to work with.
|
||||||
|
|
||||||
|
This works well for hosting an OSX VM on a local network, so I can use a Windows or Linux box and still have a real screen to read messages on. I'm hoping to set it up to send messages and view attachments to further limit the number of times I have to take my phone out of my pocket or type using my thumbs. `DO NOT USE THIS ON INTERNET-FACING SYSTEMS`
|
||||||
302
chatterbox.php
Normal file
302
chatterbox.php
Normal file
@@ -0,0 +1,302 @@
|
|||||||
|
<?php
|
||||||
|
class ChatterBox {
|
||||||
|
const HANDLE_ID = 'Handle';
|
||||||
|
const DATE_ID = 'Date';
|
||||||
|
const TEXT_ID = 'Text';
|
||||||
|
const CHAT_ID = 'Chat';
|
||||||
|
const ISSENT_ID = 'IsSent';
|
||||||
|
const FIRST_ID = "FirstName";
|
||||||
|
const LAST_ID = "LastName";
|
||||||
|
|
||||||
|
const CHAT_DB = __ROOT__.'/chat.db';
|
||||||
|
const ADDR_DB = __ROOT__.'/AddressBook-v22.abcddb';
|
||||||
|
|
||||||
|
/* TODO: IMPORTANT: Replace these with your user's messages and address book files */
|
||||||
|
const CHAT_DB_SRC = '/Users/<USERNAME>/Library/Messages/chat.db';
|
||||||
|
const ADDR_DB_SRC = '/Users/<USERNAME>/Application\ Support/AddressBook/AddressBook-v22.abcddb';
|
||||||
|
|
||||||
|
public $chat_ids;
|
||||||
|
public $selected_chat;
|
||||||
|
public $filewatch;
|
||||||
|
|
||||||
|
function __construct() {
|
||||||
|
date_default_timezone_set('America/Los_Angeles');
|
||||||
|
$this->chat_ids = ChatterBox::get_chat_list();
|
||||||
|
$this->selected_chat = $this->chat_ids[0];
|
||||||
|
// Watch the write-ahead log, since that's what stores recent changes
|
||||||
|
$this->filewatch = new FileWatch(ChatterBox::CHAT_DB_SRC . '-wal');
|
||||||
|
}
|
||||||
|
|
||||||
|
function __destruct() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function check_for_changes() {
|
||||||
|
$filechanged = $this->filewatch->has_changed();
|
||||||
|
if ($filechanged) {
|
||||||
|
$this->filewatch->copy_database(ChatterBox::CHAT_DB_SRC, __ROOT__ . '/');
|
||||||
|
}
|
||||||
|
echo $filechanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get_chat_messages($chat_id) {
|
||||||
|
$chat_db = new SQLite3(ChatterBox::CHAT_DB, SQLITE3_OPEN_READONLY);
|
||||||
|
if (!$chat_db) {
|
||||||
|
error_log($chat_db->lastErrorMsg());
|
||||||
|
}
|
||||||
|
|
||||||
|
$query =
|
||||||
|
"SELECT m.date AS " . ChatterBox::DATE_ID . ", " .
|
||||||
|
"m.text AS " . ChatterBox::TEXT_ID . ", " .
|
||||||
|
"m.is_from_me AS " . ChatterBox::ISSENT_ID . ", " .
|
||||||
|
"h.id AS " . ChatterBox::HANDLE_ID . " " .
|
||||||
|
"FROM message AS m " .
|
||||||
|
"LEFT OUTER JOIN chat_message_join AS cm " .
|
||||||
|
"ON cm.message_id = m.ROWID " .
|
||||||
|
"LEFT OUTER JOIN handle as h " .
|
||||||
|
"ON m.handle_id = h.ROWID " .
|
||||||
|
"WHERE cm.chat_id = $chat_id " .
|
||||||
|
"ORDER BY m.date ASC;";
|
||||||
|
|
||||||
|
$ret = $chat_db->query($query);
|
||||||
|
if(!$ret) {
|
||||||
|
error_log( "Unable to query database. " . $chat_db->lastErrorMsg() );
|
||||||
|
} else {
|
||||||
|
while($row = $ret->fetchArray(SQLITE3_ASSOC)) {
|
||||||
|
$chat_messages[] = $row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$chat_db->close();
|
||||||
|
return $chat_messages;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function get_chat_list() {
|
||||||
|
$chat_ids = array();
|
||||||
|
$chat_db = new SQLite3(ChatterBox::CHAT_DB, SQLITE3_OPEN_READONLY);
|
||||||
|
if (!$chat_db) {
|
||||||
|
error_log($chat_db->lastErrorMsg());
|
||||||
|
return $chat_ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
$query =
|
||||||
|
"SELECT DISTINCT(cm.chat_id) AS " . ChatterBox::CHAT_ID . " " .
|
||||||
|
"FROM chat_message_join AS cm " .
|
||||||
|
"ORDER BY cm.message_date;";
|
||||||
|
|
||||||
|
$ret = $chat_db->query($query);
|
||||||
|
if(!$ret) {
|
||||||
|
error_log( "Unable to query database. " . $chat_db->lastErrorMsg() );
|
||||||
|
} else {
|
||||||
|
while($row = $ret->fetchArray(SQLITE3_ASSOC)) {
|
||||||
|
$chat_ids[] = $row[ChatterBox::CHAT_ID];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$chat_db->close();
|
||||||
|
return $chat_ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get_chat_handles($chat_id) {
|
||||||
|
$handles = array();
|
||||||
|
$chat_db = new SQLite3(ChatterBox::CHAT_DB, SQLITE3_OPEN_READONLY);
|
||||||
|
if (!$chat_db) {
|
||||||
|
error_log($chat_db->lastErrorMsg());
|
||||||
|
return $handles;
|
||||||
|
}
|
||||||
|
|
||||||
|
$query =
|
||||||
|
"SELECT h.id AS " . ChatterBox::HANDLE_ID . " " .
|
||||||
|
"FROM chat_handle_join AS ch " .
|
||||||
|
"INNER JOIN handle as h " .
|
||||||
|
" on ch.handle_id = h.ROWID " .
|
||||||
|
"WHERE ch.chat_id = $chat_id;";
|
||||||
|
|
||||||
|
$ret = $chat_db->query($query);
|
||||||
|
if(!$ret) {
|
||||||
|
error_log( "Unable to query database. " . $chat_db::lastErrorMsg() );
|
||||||
|
} else {
|
||||||
|
while($row = $ret->fetchArray(SQLITE3_ASSOC)) {
|
||||||
|
$handles[] = $row[ChatterBox::HANDLE_ID];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$chat_db->close();
|
||||||
|
return $handles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get_chat_previews() {
|
||||||
|
$chat_previews = array();
|
||||||
|
$chat_db = new SQLite3(ChatterBox::CHAT_DB, SQLITE3_OPEN_READONLY);
|
||||||
|
if (!$chat_db) {
|
||||||
|
error_log($chat_db->lastErrorMsg());
|
||||||
|
return $chat_previews;
|
||||||
|
}
|
||||||
|
|
||||||
|
$query =
|
||||||
|
"SELECT MAX(cm.message_date) AS " . ChatterBox::DATE_ID . ", " .
|
||||||
|
"cm.chat_id AS " . ChatterBox::CHAT_ID . ", " .
|
||||||
|
"m.text AS " . ChatterBox::TEXT_ID . " " .
|
||||||
|
"FROM chat_message_join AS cm " .
|
||||||
|
"INNER JOIN message AS m " .
|
||||||
|
"ON cm.message_id = m.ROWID " .
|
||||||
|
"GROUP BY cm.chat_id " .
|
||||||
|
"ORDER BY cm.message_date DESC;";
|
||||||
|
|
||||||
|
$this->chat_ids = array();
|
||||||
|
$ret = $chat_db->query($query);
|
||||||
|
if(!$ret) {
|
||||||
|
error_log( "Unable to query database. " . $chat_db->lastErrorMsg() );
|
||||||
|
} else {
|
||||||
|
while($row = $ret->fetchArray(SQLITE3_ASSOC)) {
|
||||||
|
$this->chat_ids[] = $row[ChatterBox::CHAT_ID];
|
||||||
|
$chat_previews[] = $row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$chat_db->close();
|
||||||
|
return $chat_previews;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function convert_epoch_to_date($epoch) {
|
||||||
|
return date("F d", substr($epoch, 0, -3));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function convert_epoch_to_datetime($epoch) {
|
||||||
|
return date("H:i \| F d", substr($epoch, 0, -3));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get_names_from_chat($chat_id) {
|
||||||
|
$handles = $this->get_chat_handles($chat_id);
|
||||||
|
$names = $this->get_names_from_handles($handles);
|
||||||
|
|
||||||
|
return $names;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get_names_from_handles($handles) {
|
||||||
|
$addr_db = new SQLite3(ChatterBox::ADDR_DB, SQLITE3_OPEN_READONLY);
|
||||||
|
if (!$addr_db) {
|
||||||
|
error_log($addr_db->lastErrorMsg());
|
||||||
|
}
|
||||||
|
|
||||||
|
$names = array();
|
||||||
|
foreach($handles as $handle) {
|
||||||
|
// Remove + from beginning of phone numbers
|
||||||
|
$handle = preg_replace("/^\+/", "", $handle);
|
||||||
|
$query =
|
||||||
|
"SELECT r.ZFIRSTNAME AS " . ChatterBox::FIRST_ID . ", " .
|
||||||
|
"r.ZLASTNAME AS " . ChatterBox::LAST_ID . " " .
|
||||||
|
"FROM ZABCDRECORD AS r " .
|
||||||
|
"INNER JOIN ZABCDCONTACTINDEX as i " .
|
||||||
|
"ON i.ZCONTACT = r.ROWID " .
|
||||||
|
"WHERE i.ZSTRINGFORINDEXING LIKE \"%" . $handle . "%\";";
|
||||||
|
|
||||||
|
$ret = $addr_db->querySingle($query, true);
|
||||||
|
if($ret == false) {
|
||||||
|
$names[] = $handle;
|
||||||
|
} else {
|
||||||
|
$names[] = $ret[ChatterBox::FIRST_ID] . " " . $ret[ChatterBox::LAST_ID];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$addr_db->close();
|
||||||
|
return join(", ", $names);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function display_chat_list() {
|
||||||
|
$chat_list = $this->get_chat_previews();
|
||||||
|
$chat_ids = array();
|
||||||
|
|
||||||
|
for($index = 0; $index < count($chat_list); $index++) {
|
||||||
|
$chat_id = $chat_list[$index][ChatterBox::CHAT_ID];
|
||||||
|
|
||||||
|
echo '<div id=' . $chat_id . ' class="chat_list';
|
||||||
|
//if($index == $this->selected_index) {
|
||||||
|
if($chat_id == $this->selected_chat) {
|
||||||
|
echo" active_chat";
|
||||||
|
}
|
||||||
|
echo '"><h5>';
|
||||||
|
echo $this->get_names_from_chat($chat_id);
|
||||||
|
//echo $chat_db->get_chat_handles($chat_list[$index][ChatterBox::CHAT_ID]);
|
||||||
|
echo '<span class="chat_date">';
|
||||||
|
echo $this->convert_epoch_to_date($chat_list[$index][ChatterBox::DATE_ID]);
|
||||||
|
echo '</span></h5><p>';
|
||||||
|
echo $chat_list[$index][ChatterBox::TEXT_ID];
|
||||||
|
echo '</p></div>';
|
||||||
|
$chat_ids[] = $chat_id;
|
||||||
|
}
|
||||||
|
$this->chat_ids = $chat_ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function send_message($message, $recipient) {
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
public function display_chat_history() {
|
||||||
|
$messages = $this->get_chat_messages($this->selected_chat);
|
||||||
|
|
||||||
|
for($index = 0; $index < count($messages); $index++) {
|
||||||
|
if($messages[$index][ChatterBox::ISSENT_ID]) {
|
||||||
|
echo '<div class="sent_message"><p>';
|
||||||
|
} else {
|
||||||
|
echo '<div class="received_message"><p>';
|
||||||
|
}
|
||||||
|
echo $messages[$index][ChatterBox::TEXT_ID];
|
||||||
|
echo '</p><span class="time_date">';
|
||||||
|
echo $this->convert_epoch_to_datetime(
|
||||||
|
$messages[$index][ChatterBox::DATE_ID]);
|
||||||
|
echo '</span></div>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FileWatch {
|
||||||
|
|
||||||
|
protected $watch_file = null;
|
||||||
|
protected $last_accessed = 0;
|
||||||
|
|
||||||
|
public function __construct($filename) {
|
||||||
|
$this->watch_file = $filename;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function has_changed() {
|
||||||
|
$file_changed = false;
|
||||||
|
$ret = null;
|
||||||
|
$output = null;
|
||||||
|
|
||||||
|
// Mac-variant
|
||||||
|
exec('stat -f %m ' . $this->watch_file, $output, $ret);
|
||||||
|
// POSIX-variant
|
||||||
|
// exec('stat -t -c %Y ' . $this->watch_file, $output, $ret);
|
||||||
|
if($ret) {
|
||||||
|
error_log("Unable to access file: " . $this->watch_file);
|
||||||
|
} else {
|
||||||
|
if(!$this->last_accessed || (int)$output[0] > $this->last_accessed) {
|
||||||
|
$this->last_accessed = (int)$output[0];
|
||||||
|
$file_changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $file_changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
function copy_database($source, $destination) {
|
||||||
|
$db_file = basename($source);
|
||||||
|
$src = dirname($source) . '/';
|
||||||
|
$dst = $destination;
|
||||||
|
|
||||||
|
// Copy database file
|
||||||
|
if (!copy($src . $db_file, $dst . $db_file)) {
|
||||||
|
error_log('Could not copy database');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy write-ahead log
|
||||||
|
if (!copy($src . $db_file . '-wal', $dst . $db_file . '-wal')) {
|
||||||
|
error_log('Could not copy write-ahead log');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
48
index.php
Normal file
48
index.php
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
define('__ROOT__', dirname(__FILE__));
|
||||||
|
require_once(__ROOT__.'/user_actions.php');
|
||||||
|
?>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" type="text/css" rel="stylesheet">
|
||||||
|
<!-- Latest compiled and minified CSS -->
|
||||||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
|
||||||
|
<!-- jQuery library -->
|
||||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
|
||||||
|
<!-- Latest compiled JavaScript -->
|
||||||
|
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
|
||||||
|
<!-- Custom Code -->
|
||||||
|
<script src="scripts.js"></script>
|
||||||
|
<link rel="stylesheet" href="stylesheet.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<div class="messaging">
|
||||||
|
<div class="inbox_msg">
|
||||||
|
<div class="inbox_people">
|
||||||
|
<div class="inbox_chat" id="inbox_chat">
|
||||||
|
<?php $chatterbox->display_chat_list(); ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mesgs">
|
||||||
|
<div class="msg_history" id="msg_history">
|
||||||
|
<?php $chatterbox->display_chat_history(); ?>
|
||||||
|
</div>
|
||||||
|
<div class="type_msg">
|
||||||
|
<span class="input_msg_write">
|
||||||
|
<input type="text" class="write_msg" placeholder="Type a message" />
|
||||||
|
</span>
|
||||||
|
<!-- Commented out until I figure out how to send messages
|
||||||
|
<span class="input_btn_submit">
|
||||||
|
<button class="msg_send_btn" type="button">
|
||||||
|
<i class="fa fa-paper-plane-o" aria-hidden="true"></i>
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
71
scripts.js
Normal file
71
scripts.js
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
var timer;
|
||||||
|
function message_timer() {
|
||||||
|
clearInterval(timer);
|
||||||
|
timer = setInterval(function() {
|
||||||
|
$.ajax({
|
||||||
|
method: "POST",
|
||||||
|
url: 'user_actions.php',
|
||||||
|
data:{action: 'check_for_changes'},
|
||||||
|
success:function(change_detected) {
|
||||||
|
if(change_detected) {
|
||||||
|
refresh_chat_list();
|
||||||
|
refresh_messages();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function refresh_messages() {
|
||||||
|
$.ajax({
|
||||||
|
method: "POST",
|
||||||
|
url: 'user_actions.php',
|
||||||
|
data:{action: 'refresh_messages'},
|
||||||
|
success:function(html) {
|
||||||
|
$("#msg_history").html(html);
|
||||||
|
scroll_history();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function refresh_chat_list() {
|
||||||
|
$.ajax({
|
||||||
|
method: "POST",
|
||||||
|
url: 'user_actions.php',
|
||||||
|
data: {action: 'refresh_chat_list'},
|
||||||
|
success:function(html) {
|
||||||
|
$("#inbox_chat").html(html);
|
||||||
|
set_chat_clicked();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function scroll_history() {
|
||||||
|
var d = $("#msg_history");
|
||||||
|
d.scrollTop(d.prop("scrollHeight"));
|
||||||
|
}
|
||||||
|
|
||||||
|
function set_chat_clicked() {
|
||||||
|
$(".chat_list").on('click', function(event) {
|
||||||
|
event.stopPropagation();
|
||||||
|
event.stopImmediatePropagation();
|
||||||
|
|
||||||
|
message_timer();
|
||||||
|
$.ajax({
|
||||||
|
method: "POST",
|
||||||
|
url: 'user_actions.php',
|
||||||
|
data:{action: 'set_selected_chat',
|
||||||
|
chat_id: $(this).attr('id')},
|
||||||
|
success:function(html) {
|
||||||
|
refresh_chat_list();
|
||||||
|
refresh_messages();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$(window).on('load', scroll_history);
|
||||||
|
$(window).on('load', message_timer);
|
||||||
|
|
||||||
|
$("#inbox_chat").ready(set_chat_clicked);
|
||||||
140
stylesheet.css
Normal file
140
stylesheet.css
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
body,html {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container{max-width:1170px; margin:auto;}
|
||||||
|
img{ max-width:100%;}
|
||||||
|
.inbox_people {
|
||||||
|
background: #f8f8f8 none repeat scroll 0 0;
|
||||||
|
float: left;
|
||||||
|
overflow: hidden;
|
||||||
|
width: 40%; border-right:1px solid #c4c4c4;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.inbox_msg {
|
||||||
|
border: 1px solid #c4c4c4;
|
||||||
|
clear: both;
|
||||||
|
overflow: hidden;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.recent_heading {float: left; width:40%;}
|
||||||
|
.recent_heading h4 {
|
||||||
|
color: #05728f;
|
||||||
|
font-size: 21px;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat_img {
|
||||||
|
float: left;
|
||||||
|
width: 11%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inbox_chat {
|
||||||
|
overflow-y: scroll;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.chat_list h5{ font-size:15px; color:#464646; margin:0 0 8px 0;}
|
||||||
|
.chat_list h5 span{ font-size:13px; float:right;}
|
||||||
|
.chat_list p{ font-size:14px; color:#989898; margin:auto}
|
||||||
|
.chat_list {
|
||||||
|
border-bottom: 1px solid #c4c4c4;
|
||||||
|
margin: 0;
|
||||||
|
padding: 18px 16px 10px 15px;
|
||||||
|
overflow:hidden;
|
||||||
|
clear:both;
|
||||||
|
float: left;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.active_chat{ background:#ebebeb;}
|
||||||
|
|
||||||
|
.received_message {
|
||||||
|
overflow:hidden;
|
||||||
|
margin:13px 0 13px;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: top;
|
||||||
|
width: 64%;
|
||||||
|
padding: 0px 0px 0px 10px;
|
||||||
|
}
|
||||||
|
.received_message p {
|
||||||
|
background: #ebebeb none repeat scroll 0 0;
|
||||||
|
border-radius: 3px;
|
||||||
|
color: #646464;
|
||||||
|
font-size: 14px;
|
||||||
|
margin: 0;
|
||||||
|
padding: 5px 10px 5px 12px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sent_message {
|
||||||
|
overflow:hidden;
|
||||||
|
margin:13px 0 13px;
|
||||||
|
float: right;
|
||||||
|
width: 64%;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
.sent_message p {
|
||||||
|
background: #05728f none repeat scroll 0 0;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-size: 14px;
|
||||||
|
margin: 0; color:#fff;
|
||||||
|
padding: 5px 5px 5px 12px;
|
||||||
|
width:100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time_date {
|
||||||
|
color: #747474;
|
||||||
|
display: block;
|
||||||
|
font-size: 12px;
|
||||||
|
margin: 8px 0 0;
|
||||||
|
}
|
||||||
|
.mesgs {
|
||||||
|
float: left;
|
||||||
|
padding: 0 0 0 5px;
|
||||||
|
width: 60%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.type_msg {
|
||||||
|
border-top: 1px solid #c4c4c4;
|
||||||
|
position: relative;
|
||||||
|
height: 5%;
|
||||||
|
min-height: 43;
|
||||||
|
}
|
||||||
|
.input_msg_write input {
|
||||||
|
float: left;
|
||||||
|
background: rgba(0, 0, 0, 0) none repeat scroll 0 0;
|
||||||
|
border: medium none;
|
||||||
|
color: #4c4c4c;
|
||||||
|
font-size: 15px;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.input_btn_submit {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.msg_send_btn {
|
||||||
|
background: #05728f none repeat scroll 0 0;
|
||||||
|
border: medium none;
|
||||||
|
border-radius: 50%;
|
||||||
|
color: #fff;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 17px;
|
||||||
|
height: 33px;
|
||||||
|
position: absolute;
|
||||||
|
padding-right: 9px;
|
||||||
|
right: 5px;
|
||||||
|
top: 5px;
|
||||||
|
width: 33px;
|
||||||
|
}
|
||||||
|
.messaging {
|
||||||
|
padding: 5px 5px 5px 5px;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.msg_history {
|
||||||
|
overflow-y: scroll;
|
||||||
|
/*height: 95%;*/
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
32
user_actions.php
Normal file
32
user_actions.php
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
if (!defined('__ROOT__')) {
|
||||||
|
define('__ROOT__', dirname(__FILE__));
|
||||||
|
}
|
||||||
|
require_once(__ROOT__.'/chatterbox.php');
|
||||||
|
|
||||||
|
if(session_status()!=PHP_SESSION_ACTIVE) {
|
||||||
|
session_start();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($_SESSION['chatterbox'])) {
|
||||||
|
// Database initialization
|
||||||
|
error_log("creating new session" . PHP_EOL);
|
||||||
|
$_SESSION['chatterbox'] = new ChatterBox();
|
||||||
|
}
|
||||||
|
$chatterbox = $_SESSION['chatterbox'];
|
||||||
|
|
||||||
|
if(isset($_POST['action'])) {
|
||||||
|
if($_POST['action'] == 'refresh_chat_list') {
|
||||||
|
$chatterbox->display_chat_list();
|
||||||
|
} else if ($_POST['action'] == 'set_selected_chat') {
|
||||||
|
$chatterbox->selected_chat = intval($_POST['chat_id']);
|
||||||
|
} else if ($_POST['action'] == 'refresh_messages') {
|
||||||
|
$chatterbox->display_chat_history();
|
||||||
|
} else if ($_POST['action'] == 'check_for_changes') {
|
||||||
|
$chatterbox->check_for_changes();
|
||||||
|
} else if ($_POST['action'] == 'send_message') {
|
||||||
|
// TODO Figure out how to send iMessages via command line
|
||||||
|
}
|
||||||
|
$_SESSION['chatterbox'] = $chatterbox;
|
||||||
|
}
|
||||||
|
?>
|
||||||
Reference in New Issue
Block a user