/
akolonin
/
aigents-java
Обзор
Документация
Войти
/
akolonin
/
aigents-java
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/main/java/net/webstructor/peer/Conversation.java
823 строки
35 KB
Anton Kolonin
LinkGrammarParser proxy
12 ноя 2021, 20:05
12 ноя 2021, 20:05
83c9071
Код
Авторство
О чём код?
/* * MIT License * * Copyright (c) 2005-2021 by Anton Kolonin, Aigents® * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package net.webstructor.peer; import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintStream; import java.io.StringReader; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import javax.json.Json; import javax.json.JsonArray; import javax.json.JsonReader; import net.webstructor.agent.Body; import net.webstructor.agent.Schema; import net.webstructor.al.AL; import net.webstructor.al.Any; import net.webstructor.al.Parser; import net.webstructor.al.Reader; import net.webstructor.al.Seq; import net.webstructor.al.Set; import net.webstructor.al.Time; import net.webstructor.al.Writer; import net.webstructor.comm.Emailer; import net.webstructor.comm.SocialCacher; import net.webstructor.comm.Socializer; import net.webstructor.comm.fb.FB; import net.webstructor.comm.vk.VK; import net.webstructor.comm.goog.GApi; import net.webstructor.core.Mistake; import net.webstructor.core.Property; import net.webstructor.core.Storager; import net.webstructor.core.Thing; import net.webstructor.data.Graph; import net.webstructor.data.GraphCacher; import net.webstructor.data.ReputationSystem; import net.webstructor.data.TextMiner; import net.webstructor.data.Transcoder; import net.webstructor.self.Self; import net.webstructor.self.Streamer; import net.webstructor.util.Array; import net.webstructor.util.Str; public class Conversation extends Responser { public static final String[] spider = new String[] {"spider","spidering","crawl","crawling"}; public static final String[] logout = new String[] {"logout","bye","cancel","stop"}; public static final String[] login = new String[] {"login","relogin","start","restart"}; public static final String[] in_site = new String[] {"site","in","url"}; private String spidering(Session session, String name, String id) { String report = null; Socializer provider = session.sessioner.body.getSocializer(name); if (provider != null && (provider.opendata() || session.trusted())) try { Collection peers; peers = session.sessioner.body.storager.getByName(name+" id", id); if (!AL.empty(peers)){ session.sessioner.body.debug("Spidering peer manually "+name+" "+id+" started"); Thing peer = (Thing)peers.iterator().next(); final Profiler fb_profiler = new Profiler(session.sessioner.body, provider,peer, name+" id",name+" token",name+" key"); report = fb_profiler.profile(peer,true);//fresh session.sessioner.body.debug("Spidering peer manually "+name+" "+id+" completed"); } } catch (Exception e) { session.sessioner.body.error("Spidering peer manually "+name+" "+id+" error",e); } return report != null ? report : session.no(); } public boolean process(Session session) { try { Storager storager = session.sessioner.body.storager; /* //TODO: with fixing bunch of unit tests //if logged peer is no longer valid, logout if (session.authenticated && session.getStoredPeer() == null){ session.authenticated = false; session.peer = null; }*/ //update "session properties" in "proxy peer" if (!session.authenticated() && setProperties(session)) return false; if (session.peer == null) { // not authenticated, but in the process session.responser = new Login(); return true; } else if (session.read(Reader.pattern(AL.i_my,logout)) || Array.contains(logout, session.input().toLowerCase())){//can logout at any point session.output(session.ok()); session.responser = new Login(); session.logout(); return false; } else //TODO: start if (session.argsCount() == 1 && Array.contains(login, session.args()[0])){//login/relogin/start/restart session.output(session.ok()); session.responser = new Login(); session.logout(); return true;//move on login process } else if (!session.authenticated() && !session.isSecurityLocal() && session.read(Reader.pattern(AL.i_my,new String[] {"secret question","secret answer"}))){ session.responser = new VerificationChange(); return true; } else if (session.authenticated()) { return doAuthenticated(storager,session); } else { session.responser = new Login();//TODO: really, just back to login? return true; } } catch (Throwable e) { session.output(session.no()+" "+Mistake.message(e)); if (e instanceof Mistake) session.sessioner.body.error("Conversation error "+(session.peer != null ? session.peer.getTitle(Peer.title_email) : "null")+": "+session.input(), e); return false; } } //TODO: move all that stuff to other place - social networks separately, root separately, etc. private boolean doAuthenticated(Storager storager,Session session){ Thing reader = new Thing(); Thing curPeer = session.getStoredPeer(); if (curPeer != null)//TODO:cleanup as it is just in case for post-mortem peer operations in tests curPeer.set(Peer.activity_time,Time.day(Time.today)); VK vk = (VK)session.sessioner.body.getSocializer("vkontakte");//TODO: validate type or make type-less /* //diagnostics if (session.trusted() && session.mood == AL.interrogation && session.read(Reader.pattern(AL.you,new String[] {"threads"}))) { StringBuilder sb = new StringBuilder(); int cnt = Thread.activeCount(); sb.append(cnt).append('\n'); Thread th[] = new Thread[cnt]; Thread.enumerate(th); for (int i = 0; i < cnt; i++) { sb.append(th[i].getState()).append('\n'); } session.output(sb.toString()); return false; } else */ if (session.mood == AL.interrogation) { return answer(session); } else //binding Social Network accounts //TODO: refactor for unification //TODO: ensure no id stealing happens (re-steal, if so) if (vk != null && session.input().indexOf("vkontakte_id=")==0){ //update VK login upon callback String ensti[] = vk.verifyRedirect(session.input()); String ok = ensti == null ? null : session.bindAuthenticated(Body.vkontakte_id, ensti[4],Body.vkontakte_token, ensti[3]); if (!ok.equals(session.ok()))//TODO: fix hack!? ensti = null; //TODO:restrict origin for better security if passing token? session.output("<html><body onload=\"top.postMessage(\'"+(ensti == null ? "Error:" : "Success:")+session.input()+"\',\'*\');top.window.vkontakteLoginComplete();\"></body></html>"); return false; }else if (session.mood == AL.declaration && !session.isSecurityLocal() && session.read(Reader.pattern(AL.i_my,session.peer,new String[] {Body.vkontakte_id,Body.vkontakte_token},256))) { String id = session.peer.getString(Body.vkontakte_id); String token = session.peer.getString(Body.vkontakte_token); String enst[]; if (vk != null && ((enst = vk.verifyToken(id, token)) != null)) { session.output(session.bindAuthenticated(Body.vkontakte_id, id,Body.vkontakte_token, enst[3])); } else session.output(session.no()); return false; } else if (session.mood == AL.declaration && !session.isSecurityLocal() && session.read(Reader.pattern(AL.i_my,session.peer,new String[] {Body.google_id,Body.google_token},256))) { String id = session.peer.getString(Body.google_id); String token = session.peer.getString(Body.google_token); String enstir[];//email,name,surname,token,id,refresh_token GApi gapi = (GApi)session.sessioner.body.getSocializer("google");//TODO:validate type or make typeless if (gapi != null && ((enstir = gapi.verifyToken(id, token)) != null)) { id = enstir[4]; session.output(session.bindAuthenticated(Body.google_id, id, Body.google_token, enstir[3])); if (session.ok().equals(session.output())) {//TODO: fix hack!? session.getStoredPeer().set(Body.google_id,id);//TODO:straighten if (!AL.empty(enstir[5]))//refresh_token as google_key session.getStoredPeer().set(Body.google_key, enstir[5]); } } else session.output(session.no()); return false; } else if (session.mood == AL.declaration && !session.isSecurityLocal() && session.read(Reader.pattern(AL.i_my,session.peer,new String[] {Body.facebook_id,Body.facebook_token},256))) { String id = session.peer.getString(Body.facebook_id); String token = session.peer.getString(Body.facebook_token); FB fb = (FB)session.sessioner.body.getSocializer("facebook");//TODO: validate type or make typeless if (fb != null && (token = fb.verifyToken(id, token)) != null) { session.output(session.bindAuthenticated(Body.facebook_id, id,Body.facebook_token, token)); } else session.output(session.no()); return false; } else if (session.mood == AL.declaration && !session.isSecurityLocal() && session.read(Reader.pattern(AL.i_my,new String[] {"email","e-mail"},"/.+@.+/"))) { session.responser = new EmailChange(); return true; } else if (session.input().length() == 0) { //repeated authentication seed for pre-authenticated session session.output(session.ok()); return false; } else if ((session.mood == AL.direction || session.mood == AL.declaration) && session.read(Reader.pattern(AL.you,new String[] {"forget","forgetting"}))) { Self.clear(session.sessioner.body,Schema.foundation); if (session.read(Reader.pattern(AL.you,new String[] {"forget everything","forget all"}))){ session.sessioner.body.archiver.clear(); if (session.sessioner.body.sitecacher != null) session.sessioner.body.sitecacher.clear(true);//clear with LTM if (session.sessioner.body.filecacher != null) session.sessioner.body.filecacher.clear(true,null);//clear cache entirely } session.output(session.ok()); return false; } else if ((session.mood == AL.direction || session.mood == AL.declaration) && session.read(Reader.pattern(AL.you,new String[] {"think","thinking"}))) { Peer.rethink(session.sessioner.body,session.getStoredPeer());//this does think along the way! session.output(session.ok()); return false; } else if (session.mood == AL.direction && session.read(Reader.pattern(AL.you,spider))) { Thing task = new Thing(); session.output(session.no()); if (session.read(new Seq(new Object[]{ new Any(1,AL.you),new Any(1,spider),new Property(task,"network"),"id",new Property(task,"id")}))) { session.output(spidering(session, task.getString("network"), task.getString("id"))); } else if (session.read(new Seq(new Object[]{ new Any(1,AL.you),new Any(1,spider),new Property(task,"network")}))) { final Socializer provider = session.sessioner.body.getSocializer(task.getString("network")); if (provider != null){ Thing arg = new Thing(); session.read(arg,new String[]{"block"}); final long block = Long.parseLong(arg.getString("block","-1")); session.output(session.ok()+" Spidering."); //TODO use unified thread pool? new Thread() { public void run() { provider.resync(block); } }; } } else { //TODO unify with "profiling" below boolean started = session.getBody().act("profile", task); session.output((started ? session.ok()+" " : session.no())+" " + "My "+Self.profiling[0]+"."); } return false; } else if (session.mood == AL.direction && session.read(Reader.pattern(AL.you,Self.profiling))) { //you profile|profiling [<network> [, email <email>] [, name <name>] [, surname <surname>]] Thing task = new Thing(); session.read(new Seq(new Object[]{new Any(1,AL.you),new Any(1,Self.profiling),new Property(task,"network")}));//optional network id if (session.sessioner.body.getSocializer(task.getString("network")) == null)//TODO Property-level domain validation task.setString("network", null); if (!session.trusted()) task.addThing("peers",curPeer);//profile itself only else { Collection peers; if (session.read(task,new String[]{"email","name","surname"}) >= 1 && !AL.empty(peers = storager.get(new Thing(task,Login.login_context),null))) for (Object p : peers) task.addThing("peers", (Thing)p); } //TODO unify with "spidering" above boolean started = session.getBody().act("profile", task); session.output((started ? session.ok()+" " : session.no())+" " + "My "+Self.profiling[0]+"."); return false; } else //counting users if (session.trusted() && (session.mood == AL.direction || session.mood == AL.declaration) && session.argsCount() <= 3 && session.read(Reader.pattern(AL.you,new String[] {"count","counting"}))) { StringBuilder sb = new StringBuilder(); try { Collection peers = (Collection)session.sessioner.body.storager.getByName(AL.is,Schema.peer); session.sessioner.body.debug("Counting"); if (!AL.empty(peers)){ for (Iterator it = peers.iterator(); it.hasNext();){ Thing peer = (Thing)it.next(); Collection news = peer.getThings(AL.news); Collection trusts = peer.getThings(AL.trusts); Collection topics = peer.getThings(AL.topics); Collection sites = peer.getThings(AL.sites); Collection ignores = peer.getThings(AL.ignores); Collection trustedtopics = AL.empty(topics) || AL.empty(trusts) ? null : new ArrayList(topics); if (!AL.empty(trustedtopics)) trustedtopics.retainAll(trusts); Collection trustedSites = AL.empty(sites) || AL.empty(trusts) ? null : new ArrayList(sites); if (!AL.empty(trustedSites)) trustedSites.retainAll(trusts); if (sb.length() > 0) sb.append('\n'); String name = peer.getString(AL.email); if (AL.empty(name)) name = peer.getTitle(Peer.title); sb.append(AL.empty(news)? "0" : ""+news.size()).append(' ') .append(AL.empty(trusts)? "0" : ""+trusts.size()).append(' ') .append(AL.empty(topics)? "0" : ""+topics.size()).append(' ') .append(AL.empty(sites)? "0" : ""+sites.size()).append(' ') .append(AL.empty(trustedtopics)? "0" : ""+trustedtopics.size()).append(' ') .append(AL.empty(trustedSites)? "0" : ""+trustedSites.size()).append(' ') .append(AL.empty(ignores)? "0" : ""+ignores.size()).append(' ') .append(name).append(' ') .append(peer.get(Peer.activity_time) == null ? "-" : Time.day((Date)peer.get(Peer.activity_time),false)) ; } } File temp = session.sessioner.body.getFile("stats.txt"); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(temp), "UTF-8")); writer.write(sb.toString()); writer.close(); session.output(session.ok()); } catch (Exception e) { session.sessioner.body.error("Counting error ", e); session.output(session.no()); } return false; } else //saving/loading if ((session.mood == AL.direction || session.mood == AL.declaration) && session.argsCount() <= 4 && session.read(Reader.pattern(AL.you,Self.saving))) { session.output(session.no()); Thing saver = new Thing(); if (!session.trusted()) ;//TODO: "No right" handling else if (session.read(new Seq(new Object[]{ new Any(1,AL.you), new Any(1,Self.saving), new Property(saver,Body.store_path), }))){ if (Self.save(session.getBody(), saver.getString(Body.store_path))) session.output(session.ok()); }else{ if (session.sessioner.body.sitecacher != null) session.sessioner.body.sitecacher.saveGraphs();//flush if (Self.save(session.getBody(), session.sessioner.body.self().getString(Body.store_path))) session.output(session.ok()); } return false; } else if ((session.mood == AL.direction || session.mood == AL.declaration) && session.read(Reader.pattern(AL.you,Self.loading))) { session.output(session.no()); Thing loader = new Thing(); if (session.read(new Seq(new Object[]{ new Any(1,AL.you), new Any(1,Self.loading), new Property(loader,Body.store_path), }))) //TODO:do we really need clear here? if (Self.load(session.getBody(), loader.getString(Body.store_path))) session.output(session.ok()); return false; } else //crawling web if ((session.mood == AL.direction || session.mood == AL.declaration) && session.read(Reader.pattern(AL.you,Self.reading))) { session.output(session.no()); //TODO: understand context of 'knows': test_o("You reading 'sun flare' ... - must be test_o("You reading sun flare ... Collection topics = (Collection) session.getStoredPeer().get(AL.topics); if (!AL.empty(topics)) { if (session.read(new Seq(new Object[]{ new Any(1,AL.you),new Any(1,Self.reading),new Property(reader,"thingname",1000), new Any(1,in_site),new Property(reader,"url",1000) }))) { reader.setString("range","3");//default, for test compatibility so far session.read(reader,new String[]{"range","limit","minutes"}); if (session.getBody().act("read", reader)) session.output("My "+Self.reading[0]+" "+reader.getString("thingname")+ " in "+Writer.toString(reader.getString("url"))+".");//session.ok(); } else // can fail if thingname is not supplied // TODO: decide what to do with this hack - needed for polymorphysm in argments! fix tests? if (session.read(new Seq(new Object[]{ new Any(1,AL.you),new Any(1,Self.reading), new Any(1,in_site),new Property(reader = new Thing(),"url",1000) }))) { reader.setString("range","3");//default, for test compatibility so far session.read(reader,new String[]{"range","limit","minutes"}); if (session.getBody().act("read", reader)) session.output("My "+Self.reading[0]+" site "+Writer.toString(reader.getString("url"))+".");//session.ok(); } else { //NOTE range = 1 //TODO:use reader with arguments for async spawn!? //session.read(reader,new String[]{"range","limit","minutes"}); if (session.getBody().act("read", null))//just read all sites altogether session.output(session.ok()+" My "+Self.reading[0]+"."); else session.output(session.no()+" My "+Self.reading[0]+"."); } } return false; } else if ((session.mood == AL.direction || session.mood == AL.declaration) && (session.argsCount() > 2 && "load".equals(session.args()[0]))) { //&& session.read(new Seq(new Object[]{"load","file",new Property(reader,"file",1000),"as",new Property(reader,"file",50)}))) { //TODO: fix reader to skip commas so we can read arguments into thing //TODO: support formats: csv/tsv/json/html String file = Str.arg(session.args(), "file", null); String as = Str.arg(session.args(), "as", null); if (!AL.empty(file) && !AL.empty(as)) { Collection ases = session.getStorager().getNamed(as); if (AL.single(ases)) { try { //default is csv //TODO: delimiter: ","/"\t" int loaded = new Streamer(session.getBody()).loadCSV(file, (Thing)ases.iterator().next(), curPeer); if (loaded > 0) { session.output(session.ok()+" "+loaded+" things."); return false; } } catch (Exception e) { session.getBody().error("Loading "+file+" as "+as,e); } } } session.output(session.no()); return false; } else if ((session.mood == AL.direction || session.mood == AL.declaration) && session.read(new Seq(new Object[]{"classify","rudeness","text",new Property(reader,"text",2000)}))) { session.output(session.no()); String text = reader.getString("text"); if (!AL.empty(text)){ String format = session.getString(AL.format); //text = AL.unquote(text);//TODO: unquoting is overkill here? ArrayList rc = new ArrayList(); int rudeness = session.sessioner.body.languages.rudeness(text, rc); //HACK: "reuse" reader reader.setString("text", text); reader.setString("rudeness", String.valueOf(rudeness)); //TODO do format conversion inside format(...) below if ("json".equals(format)) { reader.set("rudenesses", rc.toArray()); } else { if (rc.size() > 0) reader.set("rudenesses", Array.toSet(rc.toArray())); } Collection rs = new ArrayList(); rs.add(reader); session.output(Responser.format(null, session, curPeer, null, rs)); } return false; } else if ((session.mood == AL.direction || session.mood == AL.declaration) && session.read(new Seq(new Object[]{"classify","sentiment","text",new Property(reader,"text",4096)}))) { session.output(session.no()); String text = reader.getString("text"); if (!AL.empty(text)){ String format = session.getString(AL.format); //text = AL.unquote(text);//TODO: unquoting is overkill here? ArrayList pc = new ArrayList(); ArrayList nc = new ArrayList(); int[] pns = session.sessioner.body.languages.sentiment(text, pc, nc); //HACK: "reuse" reader reader.setString("text", text); reader.setString("positive", String.valueOf(pns[0])); reader.setString("negative", String.valueOf(pns[1])); reader.setString("sentiment", String.valueOf(pns[2])); //TODO do format conversion inside format(...) below if ("json".equals(format)) { reader.set("positives", pc.toArray()); reader.set("negatives", nc.toArray()); } else { if (pc.size() > 0) reader.set("positives", Array.toSet(pc.toArray())); if (nc.size() > 0) reader.set("negatives",Array.toSet(nc.toArray())); } Collection rs = new ArrayList(); rs.add(reader); session.output(Responser.format(null, session, curPeer, null, rs)); } return false; } else if ((session.mood == AL.direction || session.mood == AL.declaration) && session.read(new Seq(new Object[]{new Any(1,AL.you),"cluster"}))) { session.output(session.no()); String json = null; String[] texts = null; //get all docs if (session.read(new Seq(new Object[]{new Any(1,AL.you),"cluster","format","json","texts", new Property(reader,"texts",1000)})) && !AL.empty((json = reader.getString("texts")))){ //TODO: JSON JsonReader jr = Json.createReader(new StringReader(json)); JsonArray ja = jr.readArray(); if (ja != null && ja.size() > 0 && ja.getString(0) instanceof String) { texts = new String[ja.size()]; for (int i = 0; i < ja.size(); i++) texts[i] = ja.getString(i); } } else { Collection news = session.getStoredPeer().getThings(AL.trusts); if (!AL.empty(news)) texts = Thing.toStrings(news,AL.text); } //TODO: clustering via adapter { if (!AL.empty(texts)){ TextMiner m = new TextMiner(session.getBody(),null,false).setDocuments(texts).cluster(); if (json != null) { Thing data = new Thing(); data.set("categories", m.getCategoryNames()); data.set("category_documents", m.getCategoryDocuments()); data.set("category_features", m.getCategoryFatures()); session.output(Writer.toJSON(data,null)); } else session.output("You topics "+Writer.toString(m.getCategoryNames())+"." +TextMiner.toString(m.getCategoryDocuments(),AL.sites,",",";\n")+"\n" +TextMiner.toString(m.getCategoryFatures(),AL.patterns,",",";\n")); } } return false; } else if (tryAlerter(storager,session))//if alert sent successflly return false;//no further interaction is needed else if (tryEmail(storager,session))//if email send tried successflly return false;//no further interaction is needed else if (tryRSS(storager,session))//if RSS feed tried successflly return false;//no further interaction is needed else if (tryParse(storager,session))//if parsing tried successflly return false;//no further interaction is needed else if (tryGraph(storager,session))//if graphing tried successfully return false;//no further interaction is needed else if (tryReputationer(storager,session))//if graphing tried successfully return false;//no further interaction is needed else if (session.mood == AL.declaration || session.mood == AL.direction) { if (handleIntent(session)) return false;; session.output(session.no()); return false; } //TODO: if such fallthrough is needed? session.output("Dear " + (session.peer != null ? session.peer.getTitle(Peer.title) : "friend") + ", please contact us for help at "+Body.ORIGINSITE+"."); return false; }//doAuthenticated //TODO: A MUST - move to other place to avoid concurrent use of files ad redundant memory use HashMap reputationers = new HashMap(); boolean tryReputationer(Storager storager,Session session) { int rs = -1; Thing arg = new Thing(); if (!session.trusted())//for superusers only, so far... return false; if (Str.has(session.args(),"reputation","update")) { session.read(new Seq(new Object[]{"update",new Property(arg,"network")})); boolean updated = session.getBody().act("reputation update", arg); session.output(updated ? session.ok() : session.no()); return true; } if (!session.read(new Seq(new Object[]{"reputation","network",new Property(arg,"word")})) && !session.read(new Seq(new Object[]{new Property(arg,"word"),"reputation"}))) return false; String format = session.getStoredPeer().getString("format"); boolean json = format != null && format.toLowerCase().equals("json"); final Charset charset = StandardCharsets.UTF_8; ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream ps; String result = null; try { String network = arg.getString("word"); ReputationSystem r = SocialCacher.getReputationSystem(session.getBody(), network); ps = new PrintStream(baos, true, charset.name()); //TODO: get data as object!? //TODO return error code in json rs = Reputationer.act(session.getBody(), r, ps, session.args(), json); if (rs == 0) result = new String(baos.toByteArray(), charset); ps.close(); baos.close(); } catch (Exception e) { session.getBody().error("", e); } if (rs == -1)//method not matched return false; if (json) session.output("{\"result\" : "+rs+(rs == 0 ? ", \"data\" : "+result : "")+"}"); else session.output(rs == 0 ? session.ok()+"\n" + result : session.no()); return true; } boolean tryAlerter(Storager storager,Session session) { Thing arg = new Thing(); Collection peers; String text; if (session.args().length > 3 && session.args()[0].equalsIgnoreCase("alert") && session.read(arg,new String[]{"email","name","surname","text"}) >= 2 && !AL.empty(peers = storager.get(new Thing(arg,Login.login_context),null)) && !AL.empty(peers) && !AL.empty(text = arg.getString("text"))){ for (Iterator it = peers.iterator(); it.hasNext();){ Thing peer = (Thing)it.next(); Thing self = session.getStoredPeer(); //send notification to all matching peers of those who trust to this peer if (peer == self || peer.hasThing(AL.trusts, self)){ try { boolean updated = session.sessioner.body.update(peer, null, null, text, "- "+self.getTitle(Login.login_context)); session.output(updated ? session.ok() : session.no()); } catch (IOException e) { session.sessioner.body.error("Alerting "+peer.getTitle(Login.login_context), e); session.output(session.no()); } return true; } } } return false; } boolean tryEmail(Storager storager,Session session) { Thing arg = new Thing(); if (session.read(new Seq(new Object[]{AL.email,"to",new Property(arg,"to"),"subject",new Property(arg,"subject"),"text",new Property(arg,"text")}))){ session.read(arg,new String[]{"from"}); String from = arg.getString("from"); if (AL.empty(from)) from = session.getPeer().getString(AL.email); if (AL.empty(from)) from = session.getSelfPeer().getString(AL.email); String to = arg.getString("to"); String text = arg.getString("text"); String subject = arg.getString("subject"); if (Emailer.valid(from) && Emailer.valid(to) && !AL.empty(text)){ if (AL.empty(subject)) subject = session.sessioner.body.signature(); try { text += "\n"+session.sessioner.body.signature(); Emailer e = Emailer.getEmailer(); e.email(from,to,subject,text); session.output(session.ok()); } catch (IOException e) { session.sessioner.body.error("Sending email from "+from+" to "+to, e); session.output(session.no()); } return true; } } return false; } //TODO: /* For graph querying, the following parameters may be used network - name of the network date - date for the analysis (latest date of period for analysis, inclusively) period - number of days for the analysis to count from date to the past ids - ids of the nodes (mentioned in from/to) used as a seeds for graph expansion range - number of hops in the network to account for from source nodes - from 1 to N threshold - numeric threshold to select links with with relative link value value greater than that nodes - node types to be involved in graph expansion links - link types to be involved in graph expansion tags - tags to restrict graph expansion format - format to return results (JSON, Graph Al, etc.) */ boolean tryGraph(Storager storager,Session session) { Thing arg = new Thing(); String id; String network; if (session.read(new Seq(new Object[]{new Property(arg,"network"),"id",new Property(arg,"id"),"graph"})) && (network = arg.getString("network")) != null && (session.sessioner.body.getSocializer(network) != null || "www".equalsIgnoreCase(network)) && (id = arg.getString("id")) != null //TODO: sites url //if either or a) provider is "www" or b) provider is "public" or c) specified id is matching user id && ("www".equalsIgnoreCase(network) || session.sessioner.body.getSocializer(network).opendata() || id.equals(session.getStoredPeer().getString(network+" id"))) ) { session.read(arg,new String[]{"date","period","range","threshold","links","limit","format"}); Date date = Time.day(arg.getString("date","today"));//target date String period = arg.getString("period","7");//days back String range = arg.getString("range","1"); String threshold = arg.getString("threshold","0"); int limit = Integer.parseInt(arg.getString("limit","250")); if (limit > 500)//hard cap to save browser limit = 500; String format = arg.getString("format","al"); //TODO: request links/relationships as list of names, now let all links be included String links = arg.getString("links",null); String[] linksa = !AL.empty(links) ? links.split(" ") : null; //lazy site indexing //TODO:pass range as depth if range is greater than default!? if ("www".equalsIgnoreCase(network) && session.sessioner.body.sitecacher != null){ Graph dailygraph = session.sessioner.body.sitecacher.getGraph(date); if (dailygraph.getLinkers(id, false) == null) session.getBody().act("read", (new Thing()).set("url", id)); } Socializer socializer = session.sessioner.body.getSocializer(network);//setup graph-id to grap-label mapping Transcoder labeler = socializer != null && socializer instanceof Transcoder ? (Transcoder)socializer : null; //apply group filter to non-admin sessions if not open data and group filtering is supported //java.util.Set<String> members = !session.trusted() && socializer != null && !socializer.opendata() && socializer instanceof Grouper java.util.Set<String> members = !session.trusted() && socializer != null && socializer instanceof Grouper ? ((Grouper)socializer).getGroupPeerIds(id) : null; String graph = graphQuery(session,network,new String[]{labeler != null ? (String)labeler.recovercode(id) : id}, date, Integer.parseInt(period), Integer.parseInt(range), Integer.parseInt(threshold), limit, format, //AL.empty(links) ? null : new String[]{links}, AL.empty(linksa) ? null : linksa, labeler, members); session.output(!AL.empty(graph) ? graph : session.no()); return true; } return false; } //TODO: move out to somewhere String graphQuery(Session session, String network, String[] ids, Date date, int period, int range, int threshold, int limit, String format, String[] links, Transcoder coder, java.util.Set<String> members){ GraphCacher grapher; if (network.equalsIgnoreCase("www")){ grapher = session.sessioner.body.sitecacher; }else { Socializer provider = session.sessioner.body.getSocializer(network); grapher = provider instanceof SocialCacher ? ((SocialCacher)provider).getGraphCacher() : null; } if (grapher == null) return null; Graph result = grapher.getSubgraph(ids, date, period, range, threshold, limit, links, members, null); //TODO: revert reciprocal links here before exporting? //translate subgraphs to JSON/AL, accordingly to "format" String out = format.equalsIgnoreCase("json") ? result.toJSON() : result.toString(coder); //save memory result.clear(); return out; } boolean tryParse(Storager storager,Session session) { Thing arg = new Thing(); if ((session.mood == AL.direction || session.mood == AL.declaration) && session.read(Reader.pattern(AL.you,Self.parsing))) { session.output(session.no()); // AL: you parse <text>, format <format>, language <language>, type <all|tree|link>, features <words|phrases|emoticons> String text = session.read(new Seq(new Object[]{AL.text,new Property(arg,AL.text)})) ? arg.getString(AL.text) : null; if (!AL.empty(text)) { //TODO session.sessioner.body.languages.tokenize(); Seq tokens = Parser.parse(text,AL.commas+AL.periods+AL.spaces,false,true,true,true); Seq restricted = session.sessioner.body.languages.restrict(tokens); //parse session.read(new Seq(new Object[]{"type",new Property(arg,"type")})); session.read(new Seq(new Object[]{"language",new Property(arg,"language")})); session.read(new Seq(new Object[]{"distance",new Property(arg,"distance")}));//NgramAllParser only Set grams = session.sessioner.body.languages.parse(restricted,arg.map()); //output session.output("There text "+Writer.toString(text)+ ", tokens "+Writer.toString(tokens)+ ", grams "+Writer.toString(grams)+"."); } return true; } return false; } }