use of org.klomp.snark.comments.CommentSet in project i2p.i2p by i2p.
the class PeerCoordinator method gotCommentReq.
/**
* Called when comments are requested via ut_comment
*
* @since 0.9.31
*/
public void gotCommentReq(Peer peer, int num) {
/* TODO cache per-torrent setting, use it instead */
if (!_util.utCommentsEnabled())
return;
CommentSet comments = snark.getComments();
if (comments != null) {
int lastSent = peer.getTotalCommentsSent();
int sz;
synchronized (comments) {
sz = comments.size();
// only send if we have more than last time
if (sz <= lastSent)
return;
ExtensionHandler.locked_sendComments(peer, num, comments);
}
peer.setTotalCommentsSent(sz);
}
}
use of org.klomp.snark.comments.CommentSet in project i2p.i2p by i2p.
the class SnarkManager method stopAllTorrents.
/**
* Stop all running torrents, and close the tunnel after a delay
* to allow for announces.
* If called at router shutdown via Jetty shutdown hook -> webapp destroy() -> stop(),
* the tunnel won't actually be closed as the SimpleTimer2 is already shutdown
* or will be soon, so we delay a few seconds inline.
* @param finalShutdown if true, sleep at the end if any torrents were running
* @since 0.9.1
*/
public void stopAllTorrents(boolean finalShutdown) {
_stopping = true;
if (finalShutdown && _log.shouldLog(Log.WARN))
_log.warn("SnarkManager final shutdown");
int count = 0;
for (Snark snark : _snarks.values()) {
if (!snark.isStopped()) {
if (count == 0)
addMessage(_t("Stopping all torrents and closing the I2P tunnel."));
count++;
if (finalShutdown)
snark.stopTorrent(true);
else
stopTorrent(snark, false);
// How to do this without creating a ton of threads?
if (count % 8 == 0) {
try {
Thread.sleep(20);
} catch (InterruptedException ie) {
}
}
} else {
CommentSet cs = snark.getComments();
if (cs != null) {
synchronized (cs) {
if (cs.isModified()) {
locked_saveComments(snark, cs);
}
}
}
}
}
if (_util.connected()) {
if (count > 0) {
DHT dht = _util.getDHT();
if (dht != null)
dht.stop();
addMessage(_t("Closing I2P tunnel after notifying trackers."));
if (finalShutdown) {
long toWait = 5 * 1000;
if (SystemVersion.isARM())
toWait *= 2;
try {
Thread.sleep(toWait);
} catch (InterruptedException ie) {
}
_util.disconnect();
_stopping = false;
} else {
// Only schedule this if not a final shutdown
_context.simpleTimer2().addEvent(new Disconnector(), 60 * 1000);
}
} else {
_util.disconnect();
_stopping = false;
addMessage(_t("I2P tunnel closed."));
}
}
}
use of org.klomp.snark.comments.CommentSet in project i2p.i2p by i2p.
the class I2PSnarkServlet method displayComments.
/**
* @param er ratings enabled globally
* @param ec comments enabled globally
* @param esc comments enabled this torrent
* @since 0.9.31
*/
private void displayComments(Snark snark, boolean er, boolean ec, boolean esc, StringBuilder buf) {
Iterator<Comment> iter = null;
int myRating = 0;
CommentSet comments = snark.getComments();
boolean canRate = esc && _manager.util().getCommentsName().length() > 0;
buf.append("<div id=\"snarkCommentSection\"><table class=\"snarkCommentInfo\">\n<tr><th colspan=\"3\">").append(_t("Ratings and Comments"));
if (esc && !canRate) {
buf.append(" <span id=\"nameRequired\">");
buf.append(_t("Author name required to rate or comment"));
buf.append(" <a href=\"").append(_contextPath).append("/configure#configureAuthor\">[");
buf.append(_t("Configure"));
buf.append("]</a></span>");
} else if (esc) {
buf.append(" <span id=\"nameRequired\"><span class=\"commentAuthorName\" title=\"").append(_t("Your author name for published comments and ratings")).append("\">");
buf.append(DataHelper.escapeHTML(_manager.util().getCommentsName()));
buf.append("</span></span>");
}
buf.append("</th></tr>\n<tr id=\"commentsConfig\"><td>");
buf.append(_t("Comments"));
buf.append(":</td><td><label><input type=\"checkbox\" class=\"optbox\" name=\"enableComments\" id=\"enableComments\" ");
if (esc)
buf.append("checked=\"checked\"");
else if (!ec)
buf.append("disabled=\"disabled\"");
buf.append("> ");
buf.append(_t("Enable viewing and posting comments for this torrent"));
buf.append("</label></td><td class=\"commentAction\">");
if (ec) {
buf.append("<input type=\"submit\" name=\"setCommentsEnabled\" value=\"");
buf.append(_t("Save Preference"));
buf.append("\" class=\"accept\">");
}
buf.append("</td></tr>\n");
// new rating / comment form
if (canRate) {
buf.append("<tr id=\"newRating\">\n");
if (er) {
buf.append("<td>\n<select name=\"myRating\">\n");
for (int i = 5; i >= 0; i--) {
buf.append("<option value=\"").append(i).append("\" ");
if (i == myRating)
buf.append("selected=\"selected\"");
buf.append('>');
if (i != 0) {
for (int j = 0; j < i; j++) {
buf.append("★");
}
buf.append(' ').append(ngettext("1 star", "{0} stars", i));
} else {
buf.append("☆ ").append(_t("No rating"));
}
buf.append("</option>\n");
}
buf.append("</select>\n</td>");
} else {
buf.append("<td></td>");
}
if (esc) {
buf.append("<td id=\"addCommentText\"><textarea name=\"nofilter_newComment\" cols=\"44\" rows=\"4\"></textarea></td>");
} else {
buf.append("<td></td>");
}
buf.append("<td class=\"commentAction\"><input type=\"submit\" name=\"addComment\" value=\"");
if (er && esc)
buf.append(_t("Rate and Comment"));
else if (er)
buf.append(_t("Rate Torrent"));
else
buf.append(_t("Add Comment"));
buf.append("\" class=\"accept\"></td>\n");
buf.append("</tr>\n");
}
if (comments != null) {
synchronized (comments) {
// current rating
if (er) {
buf.append("<tr id=\"myRating\"><td>");
myRating = comments.getMyRating();
if (myRating > 0) {
buf.append(_t("My Rating")).append(":</td><td colspan=\"2\" class=\"commentRating\">");
String img = toThemeImg("rateme", "★", "");
for (int i = 0; i < myRating; i++) {
buf.append(img);
}
}
buf.append("</td></tr>");
}
if (er) {
buf.append("<tr id=\"showRatings\"><td>");
int rcnt = comments.getRatingCount();
if (rcnt > 0) {
double avg = comments.getAverageRating();
// todo format
buf.append(_t("Average Rating")).append(":</td><td>").append(avg);
// buf.append(' ').append(_t("Total Ratings")).append(": ").append(rcnt);
} else {
buf.append(_t("Average Rating")).append(":</td><td colspan=\"2\">");
buf.append(_t("No community ratings currently available"));
}
buf.append("</td></tr>");
}
if (ec) {
int sz = comments.size();
if (sz > 0)
iter = comments.iterator();
}
}
}
buf.append("</table>");
// TODO disable / enable comments for this torrent
// existing ratings / comments table
int ccount = 0;
if (iter != null) {
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm");
fmt.setTimeZone(SystemVersion.getSystemTimeZone(_context));
buf.append("<table class=\"snarkComments\">");
while (iter.hasNext()) {
Comment c = iter.next();
buf.append("<tr><td class=\"commentAuthor\">");
// TODO can't be hidden... hide if comments are hidden?
if (c.getName() != null) {
buf.append("<span class=\"commentAuthorName\">");
buf.append(DataHelper.escapeHTML(c.getName()));
buf.append("</span>");
}
buf.append("</td><td class=\"commentRating\">");
if (er) {
int rt = c.getRating();
if (rt > 0) {
String img = toThemeImg("rateme", "★", "");
for (int i = 0; i < rt; i++) {
buf.append(img);
}
}
}
buf.append("</td><td class=\"commentDate\">").append(fmt.format(new Date(c.getTime())));
buf.append("</td><td class=\"commentText\">");
if (esc) {
if (c.getText() != null) {
buf.append("<div class=\"commentWrapper\">");
buf.append(DataHelper.escapeHTML(c.getText()));
buf.append("</div></td><td class=\"commentDelete\"><input type=\"checkbox\" class=\"optbox\" name=\"cdelete.").append(c.getID()).append("\" title=\"").append(_t("Mark for deletion")).append("\">");
ccount++;
} else {
// insert empty named columns to maintain table layout
buf.append("</td><td class=\"commentDelete\">");
}
} else {
// insert empty named columns to maintain table layout
buf.append("</td><td class=\"commentDelete\">");
}
buf.append("</td></tr>\n");
}
if (esc && ccount > 0) {
// TODO format better
buf.append("<tr id=\"commentDeleteAction\"><td colspan=\"5\" class=\"commentAction\" align=\"right\"><input type=\"submit\" name=\"deleteComments\" value=\"");
buf.append(_t("Delete Selected"));
buf.append("\" class=\"delete\"></td></tr>\n");
}
buf.append("</table>");
} else if (esc) {
// buf.append(_t("No comments for this torrent"));
}
// iter != null
buf.append("</div>");
}
use of org.klomp.snark.comments.CommentSet in project i2p.i2p by i2p.
the class I2PSnarkServlet method deleteComments.
/**
* @since 0.9.31
*/
private void deleteComments(Snark snark, Map<String, String[]> postParams) {
CommentSet cs = snark.getComments();
if (cs == null)
return;
synchronized (cs) {
for (Map.Entry<String, String[]> entry : postParams.entrySet()) {
String key = entry.getKey();
if (key.startsWith("cdelete.")) {
try {
int id = Integer.parseInt(key.substring(8));
boolean changed = cs.remove(id);
if (!changed)
_log.warn("Delete of comment ID " + id + " UNSUCCESSFUL");
} catch (NumberFormatException nfe) {
}
}
}
}
}
use of org.klomp.snark.comments.CommentSet in project i2p.i2p by i2p.
the class PeerCoordinator method sendCommentReq.
/**
* Send a commment request message to the peer, if he supports it.
* @since 0.9.31
*/
void sendCommentReq(Peer peer) {
Map<String, BEValue> handshake = peer.getHandshakeMap();
if (handshake == null)
return;
BEValue bev = handshake.get("m");
if (bev == null)
return;
// unless forced at handshake time (see above)
try {
if (bev.getMap().get(ExtensionHandler.TYPE_COMMENT) != null) {
int sz = 0;
CommentSet comments = snark.getComments();
if (comments != null) {
synchronized (comments) {
sz = comments.size();
}
}
if (sz >= CommentSet.MAX_SIZE)
return;
ExtensionHandler.sendCommentReq(peer, CommentSet.MAX_SIZE - sz);
}
} catch (InvalidBEncodingException ibee) {
}
}
Aggregations