Created
October 16, 2025 14:32
-
-
Save pagetronic/d17cb35ddf48c9535745a46b79e05ad7 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * Copyright 2019 Laurent PAGE, Apache Licence 2.0 | |
| */ | |
| package live.page.hubd.content.notices; | |
| import com.mongodb.client.model.*; | |
| import live.page.hubd.system.Settings; | |
| import live.page.hubd.system.db.Db; | |
| import live.page.hubd.system.db.utils.AggregateUtils; | |
| import live.page.hubd.system.db.utils.Aggregator; | |
| import live.page.hubd.system.db.utils.Pipeline; | |
| import live.page.hubd.system.db.utils.paginer.Paginer; | |
| import live.page.hubd.system.json.Json; | |
| import live.page.hubd.system.sessions.Users; | |
| import live.page.hubd.system.socket.SocketPusher; | |
| import live.page.hubd.system.utils.Fx; | |
| import org.bson.BsonUndefined; | |
| import org.bson.conversions.Bson; | |
| import java.util.ArrayList; | |
| import java.util.Arrays; | |
| import java.util.Date; | |
| import java.util.List; | |
| public class NoticesView { | |
| public final static Aggregator grouper = new Aggregator("ids", "count", "date", "first", "read", "title", "message", "url", "icon", "channel", "type", "devices"); | |
| public static Json readClick(String id) { | |
| Json notice = Db.findById("Notices", id); | |
| if (notice != null) { | |
| Db.updateMany("Notices", Filters.or(Filters.eq("_id", notice.getId()), Filters.eq("grouper", notice.getString("grouper", "00"))), | |
| new Json() | |
| .put("$set", new Json("read", new Date())) | |
| .put("$unset", new Json("delay", "")) | |
| ); | |
| if (!notice.getString("user", "").isEmpty()) { | |
| sendNoticesCount(Users.fakeId(notice.getString("user"))); | |
| } | |
| } | |
| return notice; | |
| } | |
| public static Json getNotices(Users user, String start, String device, String next_str) { | |
| Paginer paginer = new Paginer(next_str, "-date", device != null ? 40 : 10); | |
| Pipeline pipeline = new Pipeline(); | |
| List<Bson> filters = new ArrayList<>(); | |
| filters.add(Filters.eq("user", user.getId())); | |
| Bson paging = paginer.getFilters(); | |
| Date date = new Date(); | |
| if (paging != null) { | |
| filters.add(paging); | |
| } else { | |
| if (start != null) { | |
| try { | |
| date = Fx.dateFormater.parse(start); | |
| } catch (Exception e) { | |
| return new Json("error", "UNKNOWN_DATE_FORMAT").put("needed", Fx.dateFormater.format(new Date(Settings.START_COUNT))); | |
| } | |
| } | |
| filters.add(Filters.lt("date", date)); | |
| } | |
| pipeline.add(Aggregates.match(Filters.and(filters))); | |
| pipeline.add(paginer.getLastSort()); | |
| pipeline.add(Aggregates.group("$channel", | |
| grouper.getGrouper( | |
| Accumulators.last("id", "$_id"), | |
| Accumulators.push("ids", "$_id"), | |
| Accumulators.sum("count", 1), | |
| Accumulators.first("subs", "$subs"), | |
| Accumulators.first("date", "$date"), | |
| Accumulators.last("first", "$date"), | |
| Accumulators.push("read", new Json("$cond", new Json() | |
| .put("if", new Json("$eq", Arrays.asList("$read", true))) | |
| .put("then", true) | |
| .put("else", false) | |
| ) | |
| ) | |
| ) | |
| )); | |
| pipeline.add(paginer.getFirstSort()); | |
| pipeline.add(paginer.getLimit()); | |
| pipeline.add(Aggregates.lookup("Subs", "subs", "_id", "subs")); | |
| if (device != null) { | |
| pipeline.add(Aggregates.unwind("$subs", new UnwindOptions().preserveNullAndEmptyArrays(true))); | |
| pipeline.add(Aggregates.match( | |
| Filters.or( | |
| Filters.eq("subs.device", device), | |
| Filters.eq("subs.device", null) | |
| ) | |
| )); | |
| pipeline.add(Aggregates.addFields(new Field<>("_id", "$id"))); | |
| } else { | |
| pipeline.add(Aggregates.addFields( | |
| new Field<>("_id", "$id"), | |
| new Field<>("read", new Json("$cond", | |
| new Json() | |
| .put("if", new Json("$eq", Arrays.asList(new Json("$size", "$read"), 0))) | |
| .put("then", false) | |
| .put("else", new Json("$allElementsTrue", "$read")) | |
| )), | |
| new Field<>("devices", new Json("$map", | |
| new Json("input", "$subs") | |
| .put("as", "subs") | |
| .put("in", | |
| new Json("$cond", new Json() | |
| .put("if", new Json("$eq", Arrays.asList("$$subs.device", new BsonUndefined()))) | |
| .put("then", "$$REMOVE") | |
| .put("else", "$$subs.device") | |
| ) | |
| ) | |
| ) | |
| ))); | |
| } | |
| pipeline.add(Aggregates.addFields(new Field<>("count", | |
| new Json("$cond", new Json().put("if", AggregateUtils.nullOrUndefined("$count")).put("then", 0).put("else", "$count")) | |
| ))); | |
| Json facet = new Json(); | |
| Pipeline rootPipeline = new Pipeline(); | |
| rootPipeline.add(new Json("$lookup", new Json().put("from", "Notices").put("pipeline", pipeline).put("as", "result"))); | |
| rootPipeline.add(Aggregates.unwind("$result")); | |
| rootPipeline.add(Aggregates.replaceRoot("$result")); | |
| facet.put("result", rootPipeline); | |
| if (!NoticesExtender.extenders.isEmpty()) { | |
| for (NoticesExtender extender : NoticesExtender.extenders) { | |
| Pipeline extenderPipeline = new Pipeline(); | |
| Json lookup = new Json().put("from", extender.getCollection()).put("pipeline", extender.getPipeline(user, date, paginer)).put("as", "result"); | |
| extenderPipeline.add(new Json("$lookup", lookup)); | |
| extenderPipeline.add(Aggregates.unwind("$result")); | |
| extenderPipeline.add(Aggregates.replaceRoot("$result")); | |
| facet.put(extender.key(), extenderPipeline); | |
| } | |
| } | |
| Pipeline facetPipeline = new Pipeline(); | |
| facetPipeline.add(Aggregates.limit(1)); | |
| facetPipeline.add(new Json("$facet", facet)); | |
| List<String> arrays = new ArrayList<>(); | |
| for (String keyFacet : facet.keyList()) { | |
| arrays.add("$" + keyFacet); | |
| } | |
| if (!arrays.isEmpty()) { | |
| facetPipeline.add(Aggregates.project(new Json().put("result", new Json("$concatArrays", arrays)))); | |
| } | |
| facetPipeline.add(Aggregates.unwind("$result")); | |
| facetPipeline.add(Aggregates.replaceRoot("$result")); | |
| facetPipeline.add(paginer.getFirstSort()); | |
| facetPipeline.add(paginer.getLimit()); | |
| facetPipeline.add(Aggregates.project(grouper.getProjectionOrder())); | |
| facetPipeline.add(paginer.getLastSort()); | |
| Json notices = paginer.getResult("Notices", facetPipeline); | |
| if (notices != null) { | |
| List<Json> result = notices.getListJson("result"); | |
| if (!result.isEmpty()) { | |
| List<String> ids = new ArrayList<>(); | |
| for (Json item : result) { | |
| if (item.getList("ids") != null) { | |
| ids.addAll(item.getList("ids")); | |
| } else { | |
| ids.add(item.getId()); | |
| } | |
| } | |
| receive(user, ids); | |
| } | |
| } | |
| return notices; | |
| } | |
| private static void receive(Users user, List<String> ids) { | |
| boolean notify = false; | |
| for (NoticesExtender extender : NoticesExtender.extenders) { | |
| notify = extender.receive(user, ids) || notify; | |
| } | |
| notify = Db.updateMany("Notices", Filters.in("_id", ids), | |
| new Json("$set", new Json("received", true))).getModifiedCount() > 0 || notify; | |
| if (notify) { | |
| sendNoticesCount(user); | |
| } | |
| } | |
| public static Json read(Users user, Json data) { | |
| if (user == null || user.isAnonymous()) { | |
| return new Json("error", "PLEASE_LOGIN"); | |
| } | |
| long count = 0; | |
| for (NoticesExtender extender : NoticesExtender.extenders) { | |
| count += extender.read(user, data); | |
| } | |
| Json rez = new Json("ok", false); | |
| if (data.getBoolean("readAll", false)) { | |
| rez.put("ok", true); | |
| rez.put("count", Db.updateMany("Notices", Filters.and( | |
| Filters.eq("user", user.getId()), | |
| Filters.eq("read", null) | |
| ), | |
| new Json().put("$set", new Json("read", true)) | |
| ).getModifiedCount() + count); | |
| } else if (data.containsKey("id")) { | |
| rez.put("ok", Db.updateOne("Notices", Filters.and( | |
| Filters.eq("user", user.getId()), Filters.eq("_id", data.getId()) | |
| ), | |
| new Json().put("$set", new Json("read", true)) | |
| )); | |
| } else if (data.containsKey("ids")) { | |
| rez.put("ok", true); | |
| rez.put("count", Db.updateMany("Notices", Filters.and(Filters.eq("user", user.getId()), Filters.in("_id", data.getList("ids"))), | |
| new Json().put("$set", new Json("read", true)) | |
| ).getModifiedCount() + count); | |
| } | |
| return rez; | |
| } | |
| public static Json delete(Users user, Json data) { | |
| Bson filter; | |
| if (data.getId() != null) { | |
| filter = Filters.and(Filters.eq("user", user.getId()), Filters.eq("_id", data.getId())); | |
| } else if (data.getList("ids", String.class) != null) { | |
| filter = Filters.and(Filters.eq("user", user.getId()), Filters.in("_id", data.getList("ids", String.class))); | |
| } else { | |
| return new Json("error", "INVALID_DATA"); | |
| } | |
| long count = Db.deleteMany("Notices", filter).getDeletedCount(); | |
| for (NoticesExtender extender : NoticesExtender.extenders) { | |
| count += extender.delete(user, data); | |
| } | |
| return new Json("ok", true).put("count", count); | |
| } | |
| public static String countInfo(Users user) { | |
| long count = Db.count("Notices", | |
| Filters.and( | |
| Filters.eq("user", user.getId()), | |
| Filters.lt("date", new Date()), | |
| Filters.eq("received", null) | |
| ), | |
| 100); | |
| for (NoticesExtender extender : NoticesExtender.extenders) { | |
| if (count >= 100) { | |
| break; | |
| } | |
| count += extender.count(user); | |
| } | |
| return count >= 100 ? "99+" : count + ""; | |
| } | |
| public static void sendNoticesCount(Users user) { | |
| if (user != null && !user.isAnonymous()) { | |
| SocketPusher.send("user", user.getId(), new Json("action", "notices").put("notices", NoticesView.countInfo(user))); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment