*
* 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. See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
if (!defined('LACONICA')) { exit(1); }
class Notice extends Memcached_DataObject
{
- ###START_AUTOCODE
- /* the code below is auto generated do not remove the above tag */
-
- public $__table = 'notice'; // table name
- public $id; // int(4) primary_key not_null
- public $profile_id; // int(4) not_null
- public $uri; // varchar(255) unique_key
- public $content; // varchar(140)
- public $rendered; // text()
- public $url; // varchar(255)
- public $created; // datetime() not_null
- public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
- public $reply_to; // int(4)
- public $is_local; // tinyint(1)
- public $source; // varchar(32)
-
- /* Static get */
- function staticGet($k,$v=NULL) { return Memcached_DataObject::staticGet('Notice',$k,$v); }
-
- /* the code above is auto generated do not remove the tag below */
- ###END_AUTOCODE
+ ###START_AUTOCODE
+ /* the code below is auto generated do not remove the above tag */
+
+ public $__table = 'notice'; // table name
+ public $id; // int(4) primary_key not_null
+ public $profile_id; // int(4) not_null
+ public $uri; // varchar(255) unique_key
+ public $content; // varchar(140)
+ public $rendered; // text()
+ public $url; // varchar(255)
+ public $created; // datetime() not_null
+ public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
+ public $reply_to; // int(4)
+ public $is_local; // tinyint(1)
+ public $source; // varchar(32)
+
+ /* Static get */
+ function staticGet($k,$v=NULL) { return Memcached_DataObject::staticGet('Notice',$k,$v); }
+
+ /* the code above is auto generated do not remove the tag below */
+ ###END_AUTOCODE
function getProfile() {
return Profile::staticGet('id', $this->profile_id);
$this->blowCaches(true);
$this->blowFavesCache(true);
$this->blowInboxes();
- parent::delete();
+ return parent::delete();
}
function saveTags() {
static function saveNew($profile_id, $content, $source=NULL, $is_local=1, $reply_to=NULL, $uri=NULL) {
+ $profile = Profile::staticGet($profile_id);
+
+ if (!$profile) {
+ common_log(LOG_ERR, 'Problem saving notice. Unknown user.');
+ return _('Problem saving notice. Unknown user.');
+ }
+
+ if (common_config('throttle', 'enabled') && !Notice::checkEditThrottle($profile_id)) {
+ common_log(LOG_WARNING, 'Excessive posting by profile #' . $profile_id . '; throttled.');
+ return _('Too many notices too fast; take a breather and post again in a few minutes.');
+ }
+
+ $banned = common_config('profile', 'banned');
+
+ if ( in_array($profile_id, $banned) || in_array($profile->nickname, $banned)) {
+ common_log(LOG_WARNING, "Attempted post from banned user: $profile->nickname (user id = $profile_id).");
+ return _('You are banned from posting notices on this site.');
+ }
+
$notice = new Notice();
$notice->profile_id = $profile_id;
- $notice->is_local = $is_local;
+
+ $blacklist = common_config('public', 'blacklist');
+
+ # Blacklisted are non-false, but not 1, either
+
+ if ($blacklist && in_array($profile_id, $blacklist)) {
+ $notice->is_local = -1;
+ } else {
+ $notice->is_local = $is_local;
+ }
+
$notice->reply_to = $reply_to;
$notice->created = common_sql_now();
- $notice->content = $content;
+ $notice->content = common_shorten_links($content);
$notice->rendered = common_render_content($notice->content, $notice);
$notice->source = $source;
$notice->uri = $uri;
return $notice;
}
+ static function checkEditThrottle($profile_id) {
+ $profile = Profile::staticGet($profile_id);
+ if (!$profile) {
+ return false;
+ }
+ # Get the Nth notice
+ $notice = $profile->getNotices(common_config('throttle', 'count') - 1, 1);
+ if ($notice && $notice->fetch()) {
+ # If the Nth notice was posted less than timespan seconds ago
+ if (time() - strtotime($notice->created) <= common_config('throttle', 'timespan')) {
+ # Then we throttle
+ return false;
+ }
+ }
+ # Either not N notices in the stream, OR the Nth was not posted within timespan seconds
+ return true;
+ }
+
function blowCaches($blowLast=false) {
$this->blowSubsCache($blowLast);
$this->blowNoticeCache($blowLast);
if ($this->is_local) {
$cache = common_memcache();
if ($cache) {
- $cache->delete(common_cache_key('user:notices:'.$this->profile_id));
+ $cache->delete(common_cache_key('profile:notices:'.$this->profile_id));
if ($blowLast) {
- $cache->delete(common_cache_key('user:notices:'.$this->profile_id.';last'));
+ $cache->delete(common_cache_key('profile:notices:'.$this->profile_id.';last'));
}
}
}
}
function blowPublicCache($blowLast=false) {
- if ($this->is_local) {
+ if ($this->is_local == 1) {
$cache = common_memcache();
if ($cache) {
$cache->delete(common_cache_key('public'));
# XXX: too many args; we need to move to named params or even a separate
# class for notice streams
- static function getStream($qry, $cachekey, $offset=0, $limit=20, $since_id=0, $before_id=0, $order=NULL) {
+ static function getStream($qry, $cachekey, $offset=0, $limit=20, $since_id=0, $before_id=0, $order=NULL, $since=NULL) {
if (common_config('memcached', 'enabled')) {
- # Skip the cache if this is a since_id or before_id qry
- if ($since_id > 0 || $before_id > 0) {
- return Notice::getStreamDirect($qry, $offset, $limit, $since_id, $before_id, $order);
+ # Skip the cache if this is a since, since_id or before_id qry
+ if ($since_id > 0 || $before_id > 0 || $since) {
+ return Notice::getStreamDirect($qry, $offset, $limit, $since_id, $before_id, $order, $since);
} else {
return Notice::getCachedStream($qry, $cachekey, $offset, $limit, $order);
}
}
- return Notice::getStreamDirect($qry, $offset, $limit, $since_id, $before_id, $order);
+ return Notice::getStreamDirect($qry, $offset, $limit, $since_id, $before_id, $order, $since);
}
- static function getStreamDirect($qry, $offset, $limit, $since_id, $before_id, $order) {
+ static function getStreamDirect($qry, $offset, $limit, $since_id, $before_id, $order, $since) {
$needAnd = FALSE;
- $needWhere = TRUE;
+ $needWhere = TRUE;
if (preg_match('/\bWHERE\b/i', $qry)) {
$needWhere = FALSE;
if ($since_id > 0) {
if ($needWhere) {
- $qry .= ' WHERE ';
+ $qry .= ' WHERE ';
$needWhere = FALSE;
} else {
$qry .= ' AND ';
}
- $qry .= ' notice.id > ' . $since_id;
+ $qry .= ' notice.id > ' . $since_id;
}
if ($before_id > 0) {
if ($needWhere) {
- $qry .= ' WHERE ';
+ $qry .= ' WHERE ';
$needWhere = FALSE;
} else {
$qry .= ' AND ';
$qry .= ' notice.id < ' . $before_id;
}
+ if ($since) {
+
+ if ($needWhere) {
+ $qry .= ' WHERE ';
+ $needWhere = FALSE;
+ } else {
+ $qry .= ' AND ';
+ }
+
+ $qry .= ' notice.created > \'' . date('Y-m-d H:i:s', $since) . '\'';
+ }
+
# Allow ORDER override
if ($order) {
# If outside our cache window, just go to the DB
if ($offset + $limit > NOTICE_CACHE_WINDOW) {
- return Notice::getStreamDirect($qry, $offset, $limit, NULL, NULL, $order);
+ return Notice::getStreamDirect($qry, $offset, $limit, NULL, NULL, $order, NULL);
}
# Get the cache; if we can't, just go to the DB
$cache = common_memcache();
if (!$cache) {
- return Notice::getStreamDirect($qry, $offset, $limit, NULL, NULL, $order);
+ return Notice::getStreamDirect($qry, $offset, $limit, NULL, NULL, $order, NULL);
}
# Get the notices out of the cache
# bet with our DB.
$new_notice = Notice::getStreamDirect($qry, 0, NOTICE_CACHE_WINDOW,
- $last_id, NULL, $order);
+ $last_id, NULL, $order, NULL);
if ($new_notice) {
$new_notices = array();
# Otherwise, get the full cache window out of the DB
- $notice = Notice::getStreamDirect($qry, 0, NOTICE_CACHE_WINDOW, NULL, NULL, $order);
+ $notice = Notice::getStreamDirect($qry, 0, NOTICE_CACHE_WINDOW, NULL, NULL, $order, NULL);
# If there are no hits, just return the value
return $wrapper;
}
- function publicStream($offset=0, $limit=20, $since_id=0, $before_id=0) {
+ function publicStream($offset=0, $limit=20, $since_id=0, $before_id=0, $since=NULL) {
$parts = array();
if (common_config('public', 'localonly')) {
$parts[] = 'is_local = 1';
- }
-
- if (common_config('public', 'blacklist')) {
- $parts[] = 'profile_id not in (' . implode(',', common_config('public', 'blacklist')) . ')';
+ } else {
+ # -1 == blacklisted
+ $parts[] = 'is_local != -1';
}
if ($parts) {
return Notice::getStream($qry,
'public',
- $offset, $limit, $since_id, $before_id);
+ $offset, $limit, $since_id, $before_id, NULL, $since);
}
function addToInboxes() {