@ -1,30 +1,29 @@
<?php
/*
* Codice beta v0.99.1 del GOLEMbot - 28 set 2017
*
* Opera by giomba, lucam e giuliof released by GPLv3 license
*
* codice schifo del GOLEMbot - dal 28 set 2017
*
* Opera by giomba, lucam e giuliof released under GPLv3 license
*
*/
// male, dovrebbero adeguarsi al sistema internazionale
require_once('config.php');
require_once('/data/config.php');
require_once('shared.php');
// === BEGIN ===
if (DEBUG) botlog("\n\n\n". '[II] BOT request starting at ' . date('Y-m-d H:i:s') . ' ====================' . "\n\n" );
DEBUG and botlog( '[II] BOT request starting at ' . date('Y-m-d H:i:s'));
$json = file_get_contents('php://input');
$row = json_decode($json);
if (DEBUG) botlog("[LOG] ".$json."\n");
DEBUG and botlog("[II] Incoming JSON ".$json."\n");
// Start up Memcached
$mc = new Memcached();
$mc->addServer('localhost', MEMCACHED_PORT)
or error("Something is wrong connecting to memcached daemon");
if ($mc == null) error('no memcached object instance');
if (! $mc->addServer(MEMCACHED_HOST, MEMCACHED_PORT)) {
error("something is wrong connecting to memcached daemon");
}
// Structure of managed telegram messages
/*
@ -45,7 +44,7 @@ $mc->addServer('localhost', MEMCACHED_PORT)
* |_ text § string (message_text)
* |_ entities: [{"offset":...,"length":...,"type":"italic"}]
* |_ photo, location, video
*
*
* **Callback Query**
* $row
* |_ callback_query
@ -54,34 +53,35 @@ $mc->addServer('localhost', MEMCACHED_PORT)
* |_ message § Message
* |_ inline_message_id § integer (inlineID)
* |_ ...
*/
*/
// HANDLE A CALLBACK
if (isset ($row->callback_query)) {
DEBUG and botlog('handle callback query');
$chatID = $row->callback_query->message->chat->id;
// Check if it was thrown by admitted users
in_array($row->callback_query->message->chat->username, BOT_BETA_TESTERS) or not_authorized($chatID);
in_array($row->callback_query->message->chat->username, BOT_ALLOWED_USERS) or not_authorized($chatID);
botlog('Ok authorized user pass!');
// Answer to the callback query (remove the loading sign)
if (DEBUG) i nfo("Callback Query, answering");
info("Callback Query, answering");
$url = API_URL.API_TOKEN."/answerCallbackQuery?callback_query_id=".$row->callback_query->id;
file_get_contents($url);
// Do something - insert here useful variables
$callback_data = $row->callback_query->data;
//$callback_id = $row->callback_query->id;
$inlineID = $row->callback_query->message->message_id;
$inlineID_old = $mc->get($chatID.MC_INLINE_ID);
// check if request comes from active inline item
if ($inlineID != $inlineID_old) { // expired session
// If called callback comes from an old inline item do not answer
if (DEBUG) warning("That's an old callback!");
die();
}
// Finally, check actual state and do things
$status = $mc->get($chatID.MC_STATUS);
if (!$status) {
@ -90,7 +90,7 @@ if (isset ($row->callback_query)) {
}
if (DEBUG) info("Starting from status $status");
// Callback state machine
switch ($status) {
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
@ -100,17 +100,17 @@ if (isset ($row->callback_query)) {
case STATE_IDLE:
switch ($callback_data){
case MSG_DELETE:
// remove current message
$sql = new mysqli('localhost', MYSQL_USER, MYSQL_PASSWORD, MYSQL_DB );
$sql = new Sqlite3(DBFILE );
$IDdelete = $mc->get($chatID.MC_DELETE_SCHEDULED_ID) or error("No ID to delete");
$sql->query("DELETE FROM ".MYSQL_TABLE." WHERE ID=$IDdelete")
or error("Can't make the query, SQL error ".$sql->error );
$sql->query("DELETE FROM telegram_post WHERE ID=$IDdelete")
or error("Can't make the query, SQL error ".$sql->lastErrorMsg() );
$sql->close();
$offset = $mc->get($chatID.MC_LIST_NUMBER);
if ($offset > 0) {
$offset--;
}
@ -128,37 +128,37 @@ if (isset ($row->callback_query)) {
if (DEBUG) warning("Callback request is not accepted in status $status");
die();
}
$archivedMsg = navigateMsgArchive($offset, $mc, $chatID);
$answer = editMessageText($chatID, $inlineID, $archivedMsg['text'],
"HTML", false, $archivedMsg['kbd'] );
$answer = json_decode($answer);
$mc->set($chatID.MC_LIST_NUMBER, $offset)
or $mc->replace($chatID.MC_LIST_NUMBER, $offset);
die();
break;
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* END STATE_IDLE
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* entering STATE_MSG_ANSWER - callback
* you can: (after you sent a message) choose if forward to
* channel or schedule it
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
case STATE_MSG_ANSWER: // only accessible by callback
/////// spostare di là
if (!(isset($callback_data))) {
//$mc->replace($chatID.MC_STATUS, STATE_IDLE);
wrong_action($chatID);
die();
}
switch ($callback_data) {
case MSG_YES:
// forward previously sent message
@ -167,9 +167,9 @@ if (isset ($row->callback_query)) {
or error("Something is wrong with memcached");
$msg = $mc->get($chatID.MC_FORWARD_MSG)
or error("Can't forward message\n");
forwardMessage(API_CHANNEL_ID, $msg->message->chat->id, $msg->message->message_id, FORWARD_SILENT);
// Remove kbd
$text = "Invio effettuato correttamente";
editMessageText($chatID, $inlineID, $text);
@ -178,32 +178,34 @@ if (isset ($row->callback_query)) {
//~ "&text=".urlencode($text);
//~ file_get_contents($url);
break;
case MSG_NO:
$status = $mc->replace($chatID.MC_STATUS, STATE_IDLE)
or error("Something is wrong with memcached");
// destroy saved message?
$text = "Invio annullato correttamente";
editMessageText($chatID, $inlineID, $text);
break;
case MSG_SCHEDULE:
// == from here can be put in a function ==
$status = $mc->replace($chatID.MC_STATUS, STATE_WAIT_DATE) or die();
$currentTab = array(
// == from here can be put in a function ==
info('status MSG_SCHEDULE');
$status = $mc->replace($chatID.MC_STATUS, STATE_WAIT_DATE) or error(__FILE__ . __LINE__);
$currentTab = array(
'month' => date('n'),
'year' => date('Y'),
'day' => null
);
$reply = getCalendarTab($currentTab['month'], $currentTab['year']);
$mc->set($chatID.MC_DATE_MSG, $currentTab) or $mc->replace($chatID.MC_DATE_MSG, $currentTab) or die ();
info('calendar tab: ' . $reply);
$mc->set($chatID.MC_DATE_MSG, $currentTab) or $mc->replace($chatID.MC_DATE_MSG, $currentTab) or error(__FILE__ . __LINE__);
$text="Quando vuoi inviare il messaggio?";
editMessageText($chatID, $inlineID, $text, "HTML", false, $reply);
$mc->set($chatID.MC_INLINE_ID, $inlineID) or $mc->replace($chatID.MC_INLINE_ID, $inlineID)
or error("Something is wrong with memcached");
// == end ==
@ -213,15 +215,15 @@ if (isset ($row->callback_query)) {
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* END STATE_MSG_ANSWER
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* entering STATE_WAIT_DATE - callback
* you can: choose the date of scheduled message(s)
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
case STATE_WAIT_DATE:
$currentTab = $mc->get($chatID.MC_DATE_MSG)
or error("Something is wrong with memcached");
// two cases: change page or confirm date
if ($callback_data == '>') {
// add 1 to month
@ -233,9 +235,9 @@ if (isset ($row->callback_query)) {
}
$mc->set($chatID.MC_DATE_MSG, $currentTab) or $mc->replace($chatID.MC_DATE_MSG, $currentTab)
or error("Something is wrong with memcached");
$text = "Il calendario del ".$currentTab['month']."-".$currentTab['year'];
// get new inline container
}
elseif ($callback_data == '< ') {
@ -244,9 +246,9 @@ if (isset ($row->callback_query)) {
else {
$currentTab['month'] = 12;
$currentTab['year'] -=1;
}
}
$text = "Il calendario del ".$currentTab['month']."-".$currentTab['year'];
$mc->set($chatID.MC_DATE_MSG, $currentTab) or $mc->replace($chatID.MC_DATE_MSG, $currentTab)
or error("Something is wrong with memcached");
}
@ -266,59 +268,59 @@ if (isset ($row->callback_query)) {
error("Not a numerical day, how you did it?!?");
$currentTab['day'] = $callback_data;
$mc->set($chatID.MC_DATE_MSG, $currentTab) or $mc->replace($chatID.MC_DATE_MSG, $currentTab) or die ("Failed to save data at Memcached server");
// Display time inline keyboard
$kbd = new InlineKbd;
$firstHour = date('Ynj') == $currentTab['year'].$currentTab['month'].$currentTab['day']?
date('G')+1 : 8;
for ($i = 8; $i < = 21; $i++) {
if ($i < $firstHour)
$kbd->insertItem(" ", "null");
else
$kbd->insertItem("$i".":00", $i);
if ($i == 14)
$kbd->pushLine();
}
$kbd->pushLine();
$kbd->insertItem("$EMOJI_X Annulla", MSG_ABORT);
$kbd->pushLine();
$text="A che ora vuoi inviare il messaggio?";
//~ $url = API_URL.API_TOKEN."/editMessageText?chat_id=".($chatID).
//~ "& message_id=".$inlineID .
//~ "&text=".urlencode($text)."&reply_markup=".$reply;
//~ file_get_contents($url);
editMessageText($chatID, $inlineID, $text, "HTML",
false, $kbd->getKeyboard());
$mc->replace($chatID.MC_STATUS, STATE_WAIT_TIME) or die();
break;
}
// If answer is < or > remain in current state and update calendar
$reply = getCalendarTab($currentTab['month'], $currentTab['year']);
//~ $url = API_URL.API_TOKEN."/editMessageText?chat_id=".($chatID).
//~ "& message_id=".$inlineID .
//~ "&text=".urlencode($text)."&reply_markup=".$reply;
//~ file_get_contents($url);
editMessageText($chatID, $inlineID, $text, "HTML", false, $reply);
$mc->set($chatID.MC_INLINE_ID, $inlineID) or $mc->replace($chatID.MC_INLINE_ID, $inlineID);
break;
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* END STATE_WAIT_DATE
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* entering STATE_WAIT_TIME - callback
* you can: choose the time of scheduled message(s)
@ -335,52 +337,52 @@ if (isset ($row->callback_query)) {
if (DEBUG) botlog("[EE] Not a numeric time\n");
die();
}
$currentTab = $mc->get($chatID.MC_DATE_MSG);
$msg = $mc->get($chatID.MC_FORWARD_MSG);
// Message preview in scheduling list is not formatted!
$text = htmlspecialchars($msg->message->text);
$dateObj = DateTime::createFromFormat('Y-n-j-G-e', $currentTab['year'] . '-' . $currentTab['month'] . '-' . $currentTab['day'] . '-' . $callback_data . '-Europe/Rome');
$dateObj->setTimezone(new DateTimeZone('UTC'));
$formattedDate = $dateObj->format('Y-m-d H:i:s');
// add to database (mysql)
$sql = new mysqli('localhost', MYSQL_USER, MYSQL_PASSWORD, MYSQL_DB);
$sql = new SQLite3(DBFILE );
// Build up mysql query
$value = "(";
$value .= $msg->message->message_id;
$value .= ",";
$value .= $msg->message->chat->id;
$value .= ",";
$value .= "'".$currentTab['year'].'-';
$value .= $currentTab['month'].'-';
$value .= $currentTab['day'].' ';
$value .= $callback_data.":00:00'";
$value .= "'$formattedDate'";
$value .= ",";
if (isset($text))
$value .= "'".$sql->escape_s tring($text)."'";
$value .= "'".$sql->escapeString($text)."'";
else
$value .= "''";
$value .= ",";
if (isset($msg->message->forward_from->username))
$value .= "'".$sql->escape_s tring($msg->message->forward_from->username)."'";
$value .= "'".$sql->escapeS tring($msg->message->forward_from->username)."'";
elseif (isset($msg->message->from->username))
$value .= "'".$sql->escape_s tring($msg->message->from->username)."'";
$value .= "'".$sql->escapeS tring($msg->message->from->username)."'";
else
$value .= "''";
$value .= "''";
$value .= ");";
info("Saving post in ".MYSQL_TABLE.", scheduled date: ".$value);
$query = $sql->query("INSERT INTO ".MYSQL_TABLE." (MessageID,ChatID,DateTime,Text,Author) VALUE ".$value)
or error("Can't make the query, SQL error ".$sql->error);
$query = "INSERT INTO telegram_post (MessageID,ChatID,DateTime,Text,Author) VALUES ".$value;
info('saving post in database, query: ' . $query);
$sql->query($query) or error("Can't make the query, SQL error ".$sql->lastErrorMsg());
$sql->close();
$text = "Programmazione avvenuta con successo";
editMessageText($chatID, $inlineID, $text);
break;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
@ -391,23 +393,21 @@ if (isset ($row->callback_query)) {
// HANDLE A COMMON MESSAGE (text/commands/photos...)
elseif (isset($row->message)) {
info('handling common message');
// Load variables
$chatID = $row->message->chat->id;
// Check if it was thrown by admitted users
if (in_array($row->message->from->username, BOT_ALLOWED_USERS)) {
info( ' Telegram: forwarding to channel... ');
forwardMessage(API_CHANNEL_ID, $row->message->chat->id, $row->message->message_id, FORWARD_SILENT);
}
else if (in_array($row->message->from->username, BOT_BETA_TESTERS)) {
if (in_array($row->message->from->username, BOT_ALLOWED_USERS)) {
info('authorized user ok');
// Finally, check actual state and do things
$status = $mc->get($chatID.MC_STATUS);
if (!$status) {
$mc->set($chatID.MC_STATUS, STATE_IDLE) or die(); // set status or force it to STATE_IDLE
$status = STATE_IDLE;
}
if (DEBUG) i nfo("Starting from status $status");
info("Starting from status $status");
// Reset CMD
if (($command = getCommand($row->message))['command'] == '/reset') {
warning("Reset command received");
@ -432,32 +432,32 @@ elseif (isset($row->message)) {
case STATE_IDLE:
if (($command = getCommand($row->message)) != null) {
info("Command received: $command[command] with options $command[options]");
switch ($command['command']) {
case '/help':
case '/start':
// Send some explainations about this bot
sendMessage($chatID,$WELCOME_MESSAGE, "HTML");
break;
case '/edit':
// not yet implemented
sendMessage($chatID, "Bravo! Hai trovato un comando non ancora implementato. Apri il codice su GitHub e lavoraci su");
break;
case '/list':
$archivedMsg = navigateMsgArchive(0, $mc, $chatID);
$answer = sendMessage($chatID, $archivedMsg['text'], "HTML", false, false, null, $archivedMsg['kbd']);
$answer = json_decode($answer);
// Should forward the message if is not pure text
//forwardMessage($chatID, $row['ChatID'], $row['MessageID']);
$mc->set($chatID.MC_INLINE_ID, $answer->result->message_id)
or $mc->replace($chatID.MC_INLINE_ID, $answer->result->message_id);
$mc->set($chatID.MC_LIST_NUMBER, 0)
or $mc->replace($chatID.MC_LIST_NUMBER, 0);
break;
@ -469,14 +469,14 @@ elseif (isset($row->message)) {
}
else { // not a command (text?)
// you probably want to forward a message?
// Check what kind of message is this
$kbd = new InlineKbd;
$kbd->insertItem("SI ".$EMOJI_THUMBSUP,MSG_YES);
$kbd->insertItem("NO ".$EMOJI_THUMBSDOWN,MSG_NO);
$kbd->insertItem("Programma ".$EMOJI_CLOCK,MSG_SCHEDULE);
$kbd->pushLine();
// This bot accepts only text, images, videos and locations
if (!(isset($row->message->photo) or isset($row->message->location)
or isset($row->message->video) or isset($row->message->text) )) {
@ -484,27 +484,27 @@ elseif (isset($row->message)) {
error("Not supported content");
// Program stops here
}
$mc->set($chatID.MC_FORWARD_MSG, $row)
or $mc->replace($chatID.MC_FORWARD_MSG, $row)
or error("Something is wrong with memcached");
// SetUp inline messages (OK, NO, SCHEDULE)
$text="Vuoi condividere sul canale?"; // NOME CANALE ".API_CHANNEL_ID."?";
$query = sendMessage($row->message->chat->id,
$text,
null, false, false, null,
$kbd->getKeyboard());
//~ $answer = file_get_contents($query);
$answer = json_decode($query);
$inlineID = $answer->result->message_id;
if (DEBUG) info("Callback message id: $inlineID");
$mc->replace($chatID.MC_STATUS, STATE_MSG_ANSWER);
$mc->set($chatID.MC_INLINE_ID, $inlineID) or $mc->replace($chatID.MC_INLINE_ID, $inlineID);
}
@ -512,7 +512,7 @@ elseif (isset($row->message)) {
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* END STATE_IDLE
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
default:
wrong_action($chatID);
}