import javax.imageio.*; import java.awt.image.*; import java.awt.event.*; import java.awt.*; import java.security.NoSuchAlgorithmException; import java.security.MessageDigest; import java.lang.management.*; import java.lang.reflect.*; import java.net.*; import java.io.*; import javax.swing.text.*; import javax.swing.event.*; import javax.swing.*; import java.util.concurrent.atomic.*; import java.util.concurrent.*; import java.util.regex.*; import java.util.List; import java.util.zip.*; import java.util.*; import android.app.*; import android.content.*; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.speech.RecognitionListener; import android.speech.RecognizerIntent; import android.speech.SpeechRecognizer; import android.widget.Button; import android.widget.TextView; import android.util.Log; import android.media.*; import android.app.Activity; import android.widget.*; import android.graphics.*; import android.app.Activity; import android.widget.*; import android.graphics.*; import android.app.*; import android.media.*; import android.net.*; import android.view.View; public class main { static Activity androidContext; static SpeechRecognizer sr; static final String TAG = "MyStt3Activity"; static String language = "de-DE"; static int extraResults = 1; static String voice = "Leopold"; static List history = new ArrayList(); public static void main(String[] args) throws Exception { callOpt(getMainClass(), "happy"); say("hallo"); androidContext.runOnUiThread(new Runnable() { public void run() { try { //androidMuteAudio(androidContext); newRecognizer(); } catch (Exception __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}}); sleep(); } static void newRecognizer() { sr = SpeechRecognizer.createSpeechRecognizer(androidContext); sr.setRecognitionListener(new listener()); recog(); } static class listener implements RecognitionListener { public void onReadyForSpeech(Bundle params) { callOpt(getMainClass(), "setBorderColor", 0xFF66FF66); print("SAG WAS."); } public void onBeginningOfSpeech() { callOpt(getMainClass(), "oh"); } public void onRmsChanged(float rmsdB) {} public void onBufferReceived(byte[] buffer) {} public void onEndOfSpeech() { callOpt(getMainClass(), "setBorderColor", 0xFFFFFFFF); } public void onError(int error) { //print( "error " + error); // screw the errors! try { sr.destroy(); } catch (Throwable e) { print(e); } newRecognizer(); } public void onResults(Bundle results) { //print("onResults " + results); ArrayList data = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION); final String s = data.get(0); print("Ich habe geh\u00f6rt: " + quote(s)); //print("I heard: " +structure(data)); // TODO: fix the java strings umlaut problem final boolean goodbye = match3("goodbye", s) || match3("bye", s) || match3("tsch\u00fcss", s) || match3("tsch\u00fcss ...", s); Thread _t_0 = new Thread() { public void run() { try { // get answer history.add(s); String answer; try { answer = goodbye ? "tsch\u00fcss" : answer(s, history); } catch (Throwable e) { e.printStackTrace(); answer = "Fehler"; } if (answer != null) say(answer); androidContext.runOnUiThread(new Runnable() { public void run() { try { if (goodbye) { print("\nGOODBYE!"); sr.destroy(); callOpt(getMainClass(), "disappear"); } else { sr.stopListening(); recog(); } } catch (Exception __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}}); } catch (Exception _e) { throw _e instanceof RuntimeException ? (RuntimeException) _e : new RuntimeException(_e); } } }; _t_0.start(); // end of thread } public void onPartialResults(Bundle partialResults) {} public void onEvent(int eventType, Bundle params) {} } static void recog() { Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language); intent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE,"voice.recognition.test"); intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, extraResults); sr.startListening(intent); //print("started listening"); } static void say(String s) { androidUnmuteAudio(androidContext); File mp3 = new File(getProgramDir(), "bla.mp3"); makeSpeechCereproc(s, voice, mp3); androidPlayMp3(androidContext, mp3); androidMuteAudio(androidContext); } // Leopold static boolean showPicture = true; // global switch. if false, you get the normal text display instead of the smiley static List emotions = litlist( "#1001283", "happy", "#1001284", "unhappy", "#1001285", "oh", "#1001286", "bored", "#1001287", "wide mouth"); static int borderColor = 0xFFFFFFFF; static String lastEmotion; static void emo(String emotion) { if (!showPicture) return; int i; for (i = 0; i < emotions.size(); i += 2) if (emotions.get(i+1).equalsIgnoreCase(emotion)) break; if (i >= emotions.size()) { print("Emotion not found: " + emotion); // use the last one from the list as default i -= 2; } lastEmotion = emotions.get(i+1); androidShowFullScreenImage(emotions.get(i), borderColor); } static void setBorderColor(int color) { if (color != borderColor) { borderColor = color; if (lastEmotion != null) emo(lastEmotion); } } static void happy() { emo("happy"); } static void unhappy() { emo("unhappy"); } static void oh() { emo("oh"); } static void bored() { emo("bored"); } static void wideMouth() { emo("wide mouth"); } static void disappear() { if (!showPicture) return; happy(); androidLater(1000, new Runnable() { public void run() { try { androidShowFullScreenColor(0xFFFFFFFF); } catch (Exception __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}}); } // Emoticons static synchronized String answer(String s, List history) { if (match3("wie hei\u00dft du", s)) return "Leopold"; if (match3("wie ist deutschland", s)) { unhappy(); return "es ist h\u00e4sslich"; } if (match3("wie ist \u00f6sterreich", s)) { happy(); return "es ist sehr sch\u00f6n"; } if (match3("du bist lustig", s)) { happy(); return "danke sch\u00f6n"; } happy(); return s; } static void androidLater(final int delay, final Runnable r) { Thread _t_1 = new Thread() { public void run() { try { sleep(delay); androidContext.runOnUiThread(r); } catch (Exception _e) { throw _e instanceof RuntimeException ? (RuntimeException) _e : new RuntimeException(_e); } } }; _t_1.start(); } static void androidShowFullScreenColor(int color) { ImageView iv = new ImageView(androidContext); iv.setBackgroundColor(color); androidShow(iv); } static void androidShowFullScreenImage(String imageID) { ImageView iv = new ImageView(androidContext); iv.setImageBitmap(BitmapFactory.decodeFile(loadLibrary(imageID).getPath())); androidShow(iv); } static void androidShowFullScreenImage(String imageID, int borderColor) { ImageView iv = new ImageView(androidContext); iv.setBackgroundColor(borderColor); iv.setImageBitmap(BitmapFactory.decodeFile(loadLibrary(imageID).getPath())); androidShow(iv); } static void androidUnmuteAudio(Activity androidContext) { AudioManager amanager = (AudioManager) androidContext.getSystemService(Context.AUDIO_SERVICE); amanager.setStreamMute(AudioManager.STREAM_NOTIFICATION, false); amanager.setStreamMute(AudioManager.STREAM_ALARM, false); amanager.setStreamMute(AudioManager.STREAM_MUSIC, false); amanager.setStreamMute(AudioManager.STREAM_RING, false); amanager.setStreamMute(AudioManager.STREAM_SYSTEM, false); } static void androidMuteAudio(Activity androidContext) { AudioManager amanager = (AudioManager) androidContext.getSystemService(Context.AUDIO_SERVICE); amanager.setStreamMute(AudioManager.STREAM_NOTIFICATION, true); amanager.setStreamMute(AudioManager.STREAM_ALARM, true); amanager.setStreamMute(AudioManager.STREAM_MUSIC, true); amanager.setStreamMute(AudioManager.STREAM_RING, true); amanager.setStreamMute(AudioManager.STREAM_SYSTEM, true); } static void makeSpeechCereproc(String text, String voice, File destMp3) { try { String format = "mp3"; String post = "" + htmlencode(voice) + "" + /*htmlencode*/(text) + "" + format + "\n" + ""; String url = "https://www.cereproc.com/livedemo.php"; URL _url = new URL(url); URLConnection conn = _url.openConnection(); conn.setRequestProperty("Content-Type", "text/plain;charset=UTF-8"); conn.setRequestProperty("Accept", "*/*"); conn.setRequestProperty("Accept-Encoding", "gzip, deflate"); conn.setRequestProperty("Accept-Language", "en-US,en;q=0.8,de;q=0.6"); conn.setRequestProperty("Cookie", "has_js=1; Drupal.visitor.liveDemo=p86ffzyal3tvgqfr; _ga=GA1.2.1406621623.1444122980; _gat=1"); conn.setRequestProperty("Origin", "https://www.cereproc.com"); conn.setRequestProperty("Referer", "https://www.cereproc.com/"); conn.setRequestProperty("User-Agent", "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/44.0.2403.89 Chrome/44.0.2403.89 Safari/537.36"); conn.setDoOutput(true); OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream()); writer.write(post); writer.flush(); String encoding = conn.getContentEncoding(); //print("Encoding: " + encoding); String contentType = conn.getContentType(); //print("Content type: " + contentType); byte[] response = loadBinaryPage(conn); //print("Bytes read: " + response.length); if ("gzip".equals(encoding)) response = gunzipBinaryData(response); print("Bytes unpacked: " + response.length); String s = new String(response, "UTF-8"); print(s); String oggUrl = null; List tok = htmlcoarsetok(s); for (int i = 1; i < tok.size(); i += 2) if (isTag(tok.get(i), "url")) { oggUrl = tok.get(i+1); break; } if (oggUrl == null) fail("No sound URL found"); byte[] ogg = loadBinaryPage(oggUrl); saveBinaryFile(destMp3, ogg); //print("Saved: " + destMp3.getAbsolutePath() + " (" + ogg.length + " bytes)"); } catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }} /** this class is fully thread-safe */ static class Flag { private boolean up; /** returns true if flag was down before */ public synchronized boolean raise() { return doRaise(); } private synchronized boolean doRaise() { if (!up) { up = true; notifyAll(); return true; } else return false; } public synchronized void waitUntilUp() { if (!up) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } public synchronized void waitUntilUp(long timeout) { if (!up) { try { wait(timeout); } catch (InterruptedException e) { e.printStackTrace(); } } } public synchronized boolean isUp() { return up; } public String toString() { return isUp() ? "up" : "down"; } // currently does a semi-active wait with latency = 50 ms public void waitForThisOr(Flag otherFlag) { try { while (!isUp() && !otherFlag.isUp()) Thread.sleep(50); } catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }} } // Flag // do not call in ui thread. // waits until playback done. static void androidPlayMp3(Activity androidContext, File mp3) { final MediaPlayer mPlayer = MediaPlayer.create(androidContext, Uri.fromFile(mp3)); final Flag done = new Flag(); mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { public void onCompletion(MediaPlayer mp) { mPlayer.release(); done.raise(); } }); mPlayer.start(); done.waitUntilUp(); } static File getProgramDir() { return programDir(); } static String quote(String s) { if (s == null) return "null"; return "\"" + s.replace("\\", "\\\\").replace("\"", "\\\"").replace("\r", "\\r").replace("\n", "\\n") + "\""; } static String quote(long l) { return quote("" + l); } static Object callOpt(Object o, String method, Object... args) { try { if (o instanceof Class) { Method m = callOpt_findStaticMethod((Class) o, method, args, false); if (m == null) return null; m.setAccessible(true); return m.invoke(null, args); } else { Method m = callOpt_findMethod(o, method, args, false); if (m == null) return null; m.setAccessible(true); return m.invoke(o, args); } } catch (Exception e) { throw new RuntimeException(e); } } static Method callOpt_findStaticMethod(Class c, String method, Object[] args, boolean debug) { Class _c = c; while (c != null) { for (Method m : c.getDeclaredMethods()) { if (debug) System.out.println("Checking method " + m.getName() + " with " + m.getParameterTypes().length + " parameters");; if (!m.getName().equals(method)) { if (debug) System.out.println("Method name mismatch: " + method); continue; } if ((m.getModifiers() & Modifier.STATIC) == 0 || !callOpt_checkArgs(m, args, debug)) continue; return m; } c = c.getSuperclass(); } return null; } static Method callOpt_findMethod(Object o, String method, Object[] args, boolean debug) { Class c = o.getClass(); while (c != null) { for (Method m : c.getDeclaredMethods()) { if (debug) System.out.println("Checking method " + m.getName() + " with " + m.getParameterTypes().length + " parameters");; if (m.getName().equals(method) && callOpt_checkArgs(m, args, debug)) return m; } c = c.getSuperclass(); } return null; } private static boolean callOpt_checkArgs(Method m, Object[] args, boolean debug) { Class[] types = m.getParameterTypes(); if (types.length != args.length) { if (debug) System.out.println("Bad parameter length: " + args.length + " vs " + types.length); return false; } for (int i = 0; i < types.length; i++) if (!(args[i] == null || isInstanceX(types[i], args[i]))) { if (debug) System.out.println("Bad parameter " + i + ": " + args[i] + " vs " + types[i]); return false; } return true; } static Class getMainClass() { try { return Class.forName("main"); } catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }} static class Matches { String[] m; } static boolean match3(String pat, String s) { return match3(pat, s, null); } static boolean match3(String pat, String s, Matches matches) { List tokpat = parse3(pat), toks = parse3(s); String[] m = match2(tokpat, toks); //print(structure(tokpat) + " on " + structure(toks) + " => " + structure(m)); if (m == null) return false; else { if (matches != null) matches.m = m; return true; } } static ArrayList litlist(A... a) { return new ArrayList(Arrays.asList(a)); } static RuntimeException error() { throw new RuntimeException("fail"); } static RuntimeException error(String msg) { throw new RuntimeException(msg); } static void sleep(long ms) { try { Thread.sleep(ms); } catch (Exception e) { throw new RuntimeException(e); } } static void sleep() { try { synchronized(main.class) { main.class.wait(); } } catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }} static void print() { System.out.println(); } static void print(Object o) { System.out.println(o); } static void print(long i) { System.out.println(i); } static void androidShow(final View view) { androidContext.runOnUiThread(new Runnable() { public void run() { try { androidContext.setContentView(view); } catch (Exception __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}}); } static String htmlencode(String s) { StringBuilder out = new StringBuilder(Math.max(16, s.length())); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c > 127 || c == '"' || c == '<' || c == '>' || c == '&') { out.append("&#"); out.append((int) c); out.append(';'); } else { out.append(c); } } return out.toString(); } static boolean isTag(String token, String tag) { return token.regionMatches(true, 0, "<" + tag + " ", 0, tag.length()+2) || token.regionMatches(true, 0, "<" + tag + ">", 0, tag.length()+2); } static byte[] gunzipBinaryData(byte[] data) { try { InputStream fis = new ByteArrayInputStream(data); GZIPInputStream gis = new GZIPInputStream(fis); ByteArrayOutputStream fos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len; while((len = gis.read(buffer)) != -1){ fos.write(buffer, 0, len); } fis.close(); fos.close(); return fos.toByteArray(); } catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }} static List parse3(String s) { return dropPunctuation(javaTokPlusPeriod(s)); } static File programDir() { return programDir(getProgramID()); } static File programDir(String snippetID) { return new File(userHome(), "JavaX-Data/" + formatSnippetID(snippetID)); } static File loadLibrary(String snippetID) { return loadBinarySnippet(snippetID); } // extended over Class.isInstance() to handle primitive types static boolean isInstanceX(Class type, Object arg) { if (type == boolean.class) return arg instanceof Boolean; if (type == int.class) return arg instanceof Integer; if (type == long.class) return arg instanceof Long; if (type == float.class) return arg instanceof Float; if (type == short.class) return arg instanceof Short; if (type == char.class) return arg instanceof Character; if (type == byte.class) return arg instanceof Byte; return type.isInstance(arg); } // match2 matches multiple "*" (matches a single token) wildcards and zero or one "..." wildcards (matches multiple tokens) static String[] match2(List pat, List tok) { // standard case (no ...) int i = pat.indexOf("..."); if (i < 0) return match2_match(pat, tok); pat = new ArrayList(pat); // We're modifying it, so copy first pat.set(i, "*"); while (pat.size() < tok.size()) { pat.add(i, "*"); pat.add(i+1, ""); // doesn't matter } return match2_match(pat, tok); } static String[] match2_match(List pat, List tok) { List result = new ArrayList(); if (pat.size() != tok.size()) { /*if (debug) print("Size mismatch: " + structure(pat) + " vs " + structure(tok));*/ return null; } for (int i = 1; i < pat.size(); i += 2) { String p = pat.get(i), t = tok.get(i); /*if (debug) print("Checking " + p + " against " + t);*/ if ("*".equals(p)) result.add(t); else if (!p.equalsIgnoreCase(t)) return null; } return result.toArray(new String[result.size()]); } // TODO: process CDATA? static List htmlcoarsetok(String s) { List tok = new ArrayList(); int l = s.length(); int i = 0; while (i < l) { int j = i; char c; // scan for non-tags while (j < l) { if (s.charAt(j) != '<') // regular character ++j; else if (s.substring(j, Math.min(j+4, l)).equals("")); j = Math.min(j+3, l); } else // it's a tag break; } tok.add(s.substring(i, j)); i = j; if (i >= l) break; c = s.charAt(i); // scan for tags if (c == '<') { ++j; while (j < l && s.charAt(j) != '>') ++j; // TODO: strings? if (j < l) ++j; } tok.add(s.substring(i, j)); i = j; } if ((tok.size() % 2) == 0) tok.add(""); return tok; } static byte[] loadBinaryPage(String url) throws IOException { return loadBinaryPage(new URL(url).openConnection()); } public static byte[] loadBinaryPage(URLConnection con) throws IOException { //setHeaders(con); ByteArrayOutputStream buf = new ByteArrayOutputStream(); InputStream inputStream = con.getInputStream(); int n = 0; while (true) { int ch = inputStream.read(); if (ch < 0) break; buf.write(ch); if (++n % 100000 == 0) System.err.println(" " + n + " bytes loaded."); } inputStream.close(); return buf.toByteArray(); } /** writes safely (to temp file, then rename) */ public static void saveBinaryFile(String fileName, byte[] contents) throws IOException { File file = new File(fileName); File parentFile = file.getParentFile(); if (parentFile != null) parentFile.mkdirs(); String tempFileName = fileName + "_temp"; FileOutputStream fileOutputStream = new FileOutputStream(tempFileName); fileOutputStream.write(contents); fileOutputStream.close(); if (file.exists() && !file.delete()) throw new IOException("Can't delete " + fileName); if (!new File(tempFileName).renameTo(file)) throw new IOException("Can't rename " + tempFileName + " to " + fileName); } static void saveBinaryFile(File fileName, byte[] contents) { try { saveBinaryFile(fileName.getPath(), contents); } catch (IOException e) { throw new RuntimeException(e); } } static RuntimeException fail() { throw new RuntimeException("fail"); } static RuntimeException fail(Object msg) { throw new RuntimeException(String.valueOf(msg)); } static String programID; static String getProgramID() { return programID; } static List dropPunctuation(List tok) { tok = new ArrayList(tok); for (int i = 1; i < tok.size(); i += 2) { String t = tok.get(i); if (t.length() == 1 && !Character.isLetter(t.charAt(0)) && !Character.isDigit(t.charAt(0)) && !t.equals("*")) { tok.set(i-1, tok.get(i-1) + tok.get(i+1)); tok.remove(i); tok.remove(i); i -= 2; } } return tok; } // javaTok extended with "..." token. static List javaTokPlusPeriod(String s) { List tok = new ArrayList(); int l = s.length(); int i = 0; while (i < l) { int j = i; char c; String cc; // scan for whitespace while (j < l) { c = s.charAt(j); cc = s.substring(j, Math.min(j+2, l)); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (cc.equals("/*")) { do ++j; while (j < l && !s.substring(j, Math.min(j+2, l)).equals("*/")); j = Math.min(j+2, l); } else if (cc.equals("//")) { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } tok.add(s.substring(i, j)); i = j; if (i >= l) break; c = s.charAt(i); // cc is not needed in rest of loop body cc = s.substring(i, Math.min(i+2, l)); // scan for non-whitespace if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { if (s.charAt(j) == opener) { ++j; break; } else if (s.charAt(j) == '\\' && j+1 < l) j += 2; else ++j; } } else if (Character.isJavaIdentifierStart(c)) do ++j; while (j < l && Character.isJavaIdentifierPart(s.charAt(j))); else if (Character.isDigit(c)) do ++j; while (j < l && Character.isDigit(s.charAt(j))); else if (cc.equals("[[")) { do ++j; while (j+1 < l && !s.substring(j, j+2).equals("]]")); j = Math.min(j+2, l); } else if (s.substring(j, Math.min(j+3, l)).equals("...")) j += 3; else ++j; tok.add(s.substring(i, j)); i = j; } if ((tok.size() % 2) == 0) tok.add(""); return tok; } static File loadBinarySnippet(String snippetID) { try { long id = parseSnippetID(snippetID); File f = DiskSnippetCache_getLibrary(id); if (f == null) { byte[] data = loadDataSnippetImpl(snippetID); DiskSnippetCache_putLibrary(id, data); f = DiskSnippetCache_getLibrary(id); } return f; } catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }} static String _userHome; static String userHome() { if (_userHome == null) { if (isAndroid()) _userHome = "/storage/sdcard0/"; else _userHome = System.getProperty("user.home"); //System.out.println("userHome: " + _userHome); } return _userHome; } static String formatSnippetID(String id) { return "#" + parseSnippetID(id); } static String formatSnippetID(long id) { return "#" + id; } static boolean isAndroid() { return System.getProperty("java.vendor").toLowerCase().indexOf("android") >= 0; } // Data files are immutable, use centralized cache public static File DiskSnippetCache_getLibrary(long snippetID) throws IOException { File file = new File(getGlobalCache(), "data_" + snippetID + ".jar"); return file.exists() ? file : null; } public static void DiskSnippetCache_putLibrary(long snippetID, byte[] data) throws IOException { saveBinaryFile(new File(getGlobalCache(), "data_" + snippetID).getPath() + ".jar", data); } static byte[] loadDataSnippetImpl(String snippetID) throws IOException { byte[] data; try { URL url = new URL("http://eyeocr.sourceforge.net/filestore/filestore.php?cmd=serve&file=blob_" + parseSnippetID(snippetID) + "&contentType=application/binary"); System.err.println("Loading library: " + url); try { data = loadBinaryPage(url.openConnection()); } catch (IOException e) { url = new URL("http://data.tinybrain.de/blobs/" + parseSnippetID(snippetID)); System.err.println("Loading library: " + url); data = loadBinaryPage(url.openConnection()); } System.err.println("Bytes loaded: " + data.length); } catch (FileNotFoundException e) { throw new IOException("Binary snippet #" + snippetID + " not found or not public"); } return data; } public static long parseSnippetID(String snippetID) { return Long.parseLong(shortenSnippetID(snippetID)); } static File getGlobalCache() { File file = new File(userHome(), ".tinybrain/snippet-cache"); file.mkdirs(); return file; } static String shortenSnippetID(String snippetID) { if (snippetID.startsWith("#")) snippetID = snippetID.substring(1); String httpBlaBla = "http://tinybrain.de/"; if (snippetID.startsWith(httpBlaBla)) snippetID = snippetID.substring(httpBlaBla.length()); return snippetID; } }