¿Hay alguna forma de ver el historial de notificaciones del navegador Chrome?

57

Recibo notificaciones de Chrome de varios sitios web y funcionan cuando ni siquiera tengo pestañas abiertas para esos sitios.

Pero a veces recibo estas notificaciones de Chrome cuando no estoy en mi escritorio o mirando mi computadora portátil.

Como algunas de estas notificaciones me son útiles, me gustaría poder acceder a cualquiera que me haya perdido.

¿Hay alguna forma de ver el historial de notificaciones?

paradroid
fuente
1
No lo parece Mirando esta publicación ( theverge.com/2015/10/14/9531133/… ), reorganizaron su política de notificación y la eliminaron del escritorio para ponerla en páginas web individuales. Lo único para acceder a nuevas notificaciones es hacer clic en la campana de una página de Google.
Terry
1
Parece que no: productforums.google.com/forum/#!msg/chrome/xs9PflHTfho/… - muy desafortunado.
LB--
El único lugar donde he encontrado notificaciones como lista es si el sitio web que las dispara las tiene a través de su sitio web. Chrome no parece reunirlos en algo así chrome://notificationsy no llegan al sistema operativo.
Jason Lydon el
Acepte la respuesta válida @paradroid
Satheesh

Respuestas:

31

Si tienes una Mac, ¡hay una manera! 😄

Así es como se vería la lista de notificaciones:

Así es como se vería la lista de notificaciones.

Todo lo que tienes que hacer es:

1. En Chrome, ve a:

chrome://flags/

2. Busque:

Enable native notifications. Mac

3. Habilítelo, reinicie Chrome, ya está. ¡Disfrutar!

EDITAR:

  • Es posible que ya no necesite hacer lo anterior.

A partir de Chrome 59, las notificaciones enviadas a través de la API de notificaciones o la API de extensiones de chrome.notifications serán mostradas directamente por el sistema de notificaciones nativo de macOS en lugar del propio sistema de Chrome. [ fuente ]

Esdras Lopez
fuente
2
Esto no responde a la pregunta de ver el historial de notificaciones, solo ver las notificaciones.
Bjorn
66
@BjornTipling Sí lo responde. Me pregunta si puede ver las notificaciones que se perdió mientras estaba fuera y mi método hace exactamente eso.
Esdras Lopez
1
Si coloca los enlaces como comentarios, los agregaré a su publicación para usted, @EsdrasLopez
user418150
1
@ user418150 Lo aprecio, pero ahora tengo la reputación. :) Verifique las ediciones.
Esdras López
2
El principal problema aquí es que solo almacena la notificación si no hace clic en ella. Varias veces he hecho clic en el título de un artículo interesante, solo para que no se cargue, sin embargo, todavía se eliminó de la lista de notificaciones. Por lo general, los artículos son demasiado nuevos para buscar en Google y, a menudo, el título de la notificación no coincide con el título del artículo, por lo que se pierde en las entrañas de la web.
iBorg
13

En MacOSX, tendrá el directorio de Chrome ubicado en Biblioteca / Soporte de aplicaciones. Abra la aplicación de terminal y ejecute los siguientes comandos:

cd ~/Library/Application\ Support/Google/Chrome/Default/Platform\ Notifications/
ls -la

Ahora verá archivos como este:

drwx------@  7 visi  staff   224 Jul 13 18:16 .
drwx------  75 visi  staff  2400 Jul 15 11:05 ..
-rw-------@  1 visi  staff   759 Jul 15 10:57 000003.log
-rw-------@  1 visi  staff    16 Jul 13 18:16 CURRENT
-rw-------@  1 visi  staff     0 Jul 13 18:16 LOCK
-rw-------@  1 visi  staff   147 Jul 13 18:16 LOG
-rw-------@  1 visi  staff    41 Jul 13 18:16 MANIFEST-000001

Puede ver que el más reciente es 000003.log, así que verifíquelo con el siguiente comando:

tail -n 100 000003.log

Y verá los últimos 100 elementos de este registro. Luego puede abrir la configuración de Chrome y deshabilitar la notificación de ese sitio web.

Tenga en cuenta que si tiene varios perfiles en Chrome, su ruta puede ser diferente, como esta (Perfil1 en lugar de Predeterminado):

cd ~/Library/Application\ Support/Google/Chrome/Profile\ 1/Platform\ Notifications/
Andrey Bezpalenko
fuente
3
Esta debería ser la respuesta aceptada. :)
Cody A. Ray
1
Todavía funciona en 2019 (aunque el registro necesita un poco de interpretación). Gran respuesta gracias
carpii
12

Si va a %LocalAppData%\Google\Chrome\User Data\Default\Platform Notifications, hay un archivo de registro de notificaciones pasadas.

Corey
fuente
44
bien, pero considere especificar la ruta como "% LocalAppData% \ Google \ Chrome \ User Data \ Default \ Platform Notificaciones" en lugar de hardcode. Funciona perfectamente en cualquier PC.
Dmitry Gusarov
En la carpeta / Datos de usuario, es posible que primero deba ubicar la carpeta de su perfil, como "C: \ Users \ username \ AppData \ Local \ Google \ Chrome \ UserData \ Profile 1 \ Platform Notificaciones"
Maffelu
1
Estos datos son binarios. ¿Cómo leerlo?
Gaia
En Chrome 71, y el archivo de registro está vacío. ¿Esto se deshabilitó en algún momento?
James
3
@Gaia Me pregunté lo mismo y acabo de crear un código de Java que hace un trabajo aceptable para descifrar la mayor parte. Lo publiqué a continuación: superuser.com/a/1410742/778383
Dreamspace President
3

Como parece que no es posible obtener un registro de las notificaciones directamente, si tuviera el mismo problema, haría trampa usando un emulador de teléfono Android o un teléfono, como el usuario que recomendó Pushbullet. Pero no solo hay Pushbullet, hay muchas otras aplicaciones, podríamos discutir los trucos de Android para escuchar y grabar notificaciones, en un hilo separado.

Si eres programador, tal vez puedas resolver tu problema a través de una extensión casera:

https://stackoverflow.com/questions/15949606/how-can-i-listen-to-notifications

"Puede conectar la función webkitNotifications.createNotification para que cada vez que se cree una notificación ejecute algún código en particular".

Quidam
fuente
2

Tocando algo que se mencionó un poco más arriba pero con un giro que asegura que no te pierdas la notificación en OSX:

  1. En el lado derecho de la barra superior principal, haga clic en el icono de notificación.

  2. Haga clic en la rueda dentada (abajo a la derecha de la pantalla de notificación)

  3. Seleccione Chrome para configurar cómo se muestran las notificaciones.

  4. Por defecto, se seleccionan "Banners" y pueden desaparecer automáticamente. En su lugar, seleccione el tipo de "Alerta" y permanecerán allí mientras no los reconozca.

De nada :)

Patrick St-Onge
fuente
2

Puede ver el historial de notificaciones push. En la esquina inferior derecha de la pantalla de su PC en la barra de tareas está lo que parece un globo de diálogo y si pasa el mouse sobre él, verá que en realidad se llama "notificaciones". Si hace clic en esa burbuja, mostrará sus correos electrónicos no leídos / nuevos y cualquier notificación push que no haya descartado. Vine aquí buscando esta respuesta y no la encontré, pero luego logré resolverlo. Estoy usando Windows 10.

Shea Bethell
fuente
Sí, esto es algo reciente en Win10, pero es la respuesta final para Windows.
paradroid
-1

Parece que Pushbullet puede resolver su problema. Afirman que puede ver sus notificaciones perdidas utilizando su extensión de Chrome.

https://blog.pushbullet.com/2014/10/23/easily-access-your-recent-notifications-in-chrome/

Socialorganix Contentbrandmgmt
fuente
Lea Cómo recomendar software para obtener la información mínima requerida y sugerencias sobre cómo recomendar software en Super User. Para que su respuesta sea útil incluso si los enlaces proporcionados rompen estos detalles, debe editarlos en su respuesta.
Digo reinstalar a Mónica el
Oye bien. Lo intentaré. De hecho, ya uso Pushbullet, pero no estaba al tanto de esta extensión de Chrome.
Paradroid
Parece que no puedo encontrar esta función. Apareció una notificación y no hay rastro de ella en el historial de notificaciones.
madprops
Repensé la pregunta y la trampa es esta. Si su teléfono recibe una notificación, pushbullet lo enviará a su escritorio y le informará que posiblemente tenga notificaciones no leídas (es posible que lo haya visto en su teléfono o lo que tenga). ¿Para qué sitios recibes notificaciones de Chrome? Si hay una aplicación para ello, siempre puede instalarla y luego recibirá las notificaciones de pushbullet en su escritorio / computadora portátil / lo que sea.
Socialorganix Contentbrandmgmt
1
La función "Notificaciones" en Pushbullet es solo para ver notificaciones de su teléfono Android en el escritorio, y lo mismo con iPhone si tiene un escritorio Mac. No tiene nada que ver con las notificaciones de Chrome.
Boaz
-1

Gracias a la respuesta anterior de Corey , y un sábado flojo con demasiado tiempo en mis manos, ahora puedo ver una lista de notificaciones recientes de Chrome en la consola de mi IDE, donde incluso puedo hacer clic en las URL.

El código es malo y usa heurística cruda ya que no tengo idea de la forma correcta de interpretar los datos binarios.

Pero es mucho mejor que nada. Ejemplo de salida (extracto):

https://www.finanzen.net/nachricht/aktien/kw-9-tops-und-flops-der-tecdax-aktien-in-der-vergangenen-woche-7195100
https://images.finanzen.net/mediacenter/unsortiert/TecDAX_boerse_frankfurt0016_kl.jpg
So bewegten sich die Einzelwerte des TecDAX in der zurückliegenden Handelswoche.*
KW 9: Tops und Flops der TecDAX-Aktien in der vergangenen Woche
So bewegten sich die Einzelwerte des TecDAX in der zurückliegenden Handelswoche.
HideOnTheseRoutes
Home/Index;Article/News/Index
tag-7195100
NotificationIdentifier
1061622960{


https://www.youtube.com/watch?v=W-mlD_bYKdU&feature=push-u-sub&attr_tag=0SL8UpnrTOnTECxr%3A6
https://lh5.googleusercontent.com/-raJM5SITO34/AAAAAAAAAAI/AAAAAAAAAAA/UtLljlL4Wpc/s96-c-mo/photo.jpg
New from Market Moves
Trade Recap: $1,500 in PROFITS*˜
COuAyJGY4uACEAY=
attributionTag
0SL8UpnrTOnTECxr:6{
 from Market MovesTrade Recap: $1,500 in PROFITS

Código Java digno de crucifixión:

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;




/**
 * v[1, 2019-03-02 13:00 UTC]
 *
 * by dreamspace-president.com
 */
final public class CrappyChromeNotificationHistoryReader {


    public static void main(final String[] args) {

        final File file = new File(
                "C:\\Users\\[YOUR_NAME_HERE]\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Platform Notifications\\000003.log");

        final List<ChromeNotificationStuff> notifications = obtainChromeNotificationStuff(file);
        for (ChromeNotificationStuff notification : notifications) {
            System.err.println();
            System.err.println(notification);
        }
        System.exit(0);
    }


    public static List<ChromeNotificationStuff> obtainChromeNotificationStuff(final File file) {

        final List<ChromeNotificationStuff> ret = new ArrayList<>();

        final List<DumbTokenList> listOfDumbTokenLists = doTheInsaneParsingThing(file);
        int instanceCounter = 0;
        for (DumbTokenList dtl : listOfDumbTokenLists) {

            final List<String> urls = new ArrayList<>();
            final List<String> texts = new ArrayList<>();

            for (String token : dtl.tokens) {
                if (token.startsWith("https://") || token.startsWith("http://")) {
                    urls.add(token);
                } else {
                    texts.add(token);
                }
            }


            // Remove unimportant URLs.
            for (int i = urls.size() - 1; i > 0; i--) {
                final String urlThis = urls.get(i);
                final int lenThis = urlThis.length();
                for (int ii = i - 1; ii >= 0; ii--) {
                    final String urlThat = urls.get(ii);
                    final int lenThat = urlThat.length();

                    if (lenThis > lenThat) {
                        if (urlThis.startsWith(urlThat)) {
                            final String removed = urls.remove(ii);
                            //                            System.err.println("\nREMOVED: " + removed + "\nKEPT   : " + urlThis); // because was better or equal
                            break;
                        }
                    } else {
                        if (urlThat.startsWith(urlThis)) {
                            final String removed = urls.remove(i);
                            //                            System.err.println("\nREMOVED: " + removed + "\nKEPT   : " + urlThat); // because was better or equal
                            break;
                        }
                    }

                }
            }

            ret.add(new ChromeNotificationStuff(instanceCounter, urls, texts));
            instanceCounter++;
        }

        ret.sort(null);

        return ret;
    }


    final public static class ChromeNotificationStuff implements Comparable<ChromeNotificationStuff> {


        private final int instanceCounter;
        final public List<String> urls;
        final public List<String> texts;


        private ChromeNotificationStuff(final int instanceCounter,
                                        final List<String> urls,
                                        final List<String> texts) {

            this.instanceCounter = instanceCounter;

            this.urls = Collections.unmodifiableList(urls);
            this.texts = Collections.unmodifiableList(texts);
        }


        public String toString() {

            final StringBuilder sb = new StringBuilder();
            for (String url : urls) {
                sb.append(url).append('\n');
            }
            for (String text : texts) {
                sb.append(text).append('\n');
            }
            return sb.toString();
        }


        @Override
        public int compareTo(final ChromeNotificationStuff o) { // Newest (= last) notifications first, please.

            return Integer.compare(o.instanceCounter, instanceCounter);
        }
    }




    final private static double MIN_LENGTH_DIFFERENCE_RATIO = 0.7;//0.9;
    final private static double MIN_REMAININGLINES_PERCENTAGEOF_ALLLINES = 0.2;




    final private static class DumbTokenList {


        final private static int MIN_LENGTH = 10; //6;
        final private static String[] EXTENSIONS = new String[] { ".jpg", ".jpeg", ".png", ".gif", ".html", ".htm", ".php" };
        final private static int MAX_EXTRA_CRAP_AFTER_EXTENSIONS = 3;
        final private static String SAFE_URL_CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;="; // https://stackoverflow.com/a/1547940/3500521

        final private String originalText;
        final private List<String> tokens;


        private DumbTokenList(final String textWithBinaryCrap) {

            originalText = textWithBinaryCrap;

            final List<String> tokens = new ArrayList<>();

            final Consumer<String> addTokenButTryToDecrappifyExtensionsFirstAnTing = token -> {


                if (token.startsWith("ttps://") || token.startsWith("ttp://")) {
                    token = "h" + token;
                }


                final List<String> newTokens = new ArrayList<>();

                if (token.startsWith("http")) {
                    final int tokenLength = token.length();
                    boolean found = false;
                    for (int i = 0; i < tokenLength; i++) {
                        final char c = token.charAt(i);
                        if (SAFE_URL_CHARACTERS.indexOf(c) < 0) {
                            newTokens.add(token.substring(0, i));
                            newTokens.add(token.substring(i));
                            found = true;
                            break;
                        }
                    }
                    if (!found) {
                        newTokens.add(token);
                    }
                } else {
                    newTokens.add(token);
                }

                for (String newToken : newTokens) {


                    String foundExt = null;
                    int foundExtLen = 0;
                    int foundExtAt = -1;
                    for (String extension : EXTENSIONS) {
                        final int idx = newToken.indexOf(extension);
                        if (idx >= 0) {
                            final int extLen = extension.length();
                            if (idx > foundExtAt || (idx == foundExtAt && extLen > foundExtLen)) {
                                foundExt = extension;
                                foundExtLen = extLen;
                                foundExtAt = idx;
                            }
                        }
                    }
                    if (foundExt != null) {
                        final int amountOfCharactersAfterThisFind = newToken.length() - foundExtAt - foundExtLen;
                        if (amountOfCharactersAfterThisFind <= MAX_EXTRA_CRAP_AFTER_EXTENSIONS) {
                            // OK. Shorten this bitch.
                            newToken = newToken.substring(0, foundExtAt + foundExtLen);
                        }
                    }


                    if (newToken.startsWith("http")) {
                        if (!newToken.startsWith("http://") && !newToken.startsWith("https://")) {
                            continue;
                        }
                    }


                    if (newToken.startsWith("/watch?v=")) {
                        newToken = "https://www.youtube.com" + newToken;
                    }


                    if (newToken.length() >= MIN_LENGTH) {
                        tokens.add(newToken);
                    }


                }

            };

            final StringBuilder sb = new StringBuilder();

            final int len = textWithBinaryCrap.length();
            for (int i = 0; i <= len + 1; i++) {

                final char c = i < len ? textWithBinaryCrap.charAt(i) : 0;

                if (c < ' ' || c == '"') {

                    String potentialText = sb.toString();
                    while (true) {
                        final int httpIDX = potentialText.indexOf("http", 1);
                        if (httpIDX < 0) {
                            addTokenButTryToDecrappifyExtensionsFirstAnTing.accept(potentialText);
                            break;
                        } else {
                            final String snippet = potentialText.substring(0, httpIDX);
                            potentialText = potentialText.substring(httpIDX);
                            addTokenButTryToDecrappifyExtensionsFirstAnTing.accept(snippet);
                        }
                    }

                    sb.setLength(0);

                    if (c == '"') {
                        // Skip this and the next. (thus "i < len +1")
                        i++;
                    }
                } else {
                    sb.append(c);
                }
            }


            // Remove quasi-duplicates. Sue me.
            //            System.err.println("\n*** STARTING DEDUPLICATION ***");
            final int lSize = tokens.size();
            for (int i = lSize - 1; i > 0; i--) { // (not 0 itself, wouldn't make sense)

                if (i < tokens.size()) {

                    final String entry = tokens.get(i);

                    for (int ii = i - 1; ii >= 0; ii--) { // (incl. 0)

                        final String otherEntry = tokens.get(ii);

                        final Boolean removeNoneOrFirstOrSecond = areLinesTooSimilar(entry, otherEntry);
                        if (removeNoneOrFirstOrSecond != null) {

                            if (!removeNoneOrFirstOrSecond) {
                                final String removed = tokens.remove(i);
                                //                                System.err.println("\nREMOVED: " + removed + "\nKEPT   : " + otherEntry); // because was better or equal
                            } else {
                                final String removed = tokens.remove(ii);
                                //                                System.err.println("\nREMOVED: " + removed + "\nKEPT   : " + entry); // because was better or equal
                            }
                            break; // IMPORTANT!
                        }

                    }
                }
            }


            this.tokens = Collections.unmodifiableList(tokens);

        }


        public String toString() {

            final StringBuilder sb = new StringBuilder();
            for (String token : tokens) {
                sb.append(token).append('\n');
            }
            return sb.toString();
        }


    }


    /**
     * Do NOT call with NULL/EMPTY arguments.
     *
     * @return NULL if not too similar. False if the FIRST seems superfluous. True if the SECOND seems superfluous.
     */
    private static Boolean areLinesTooSimilar(final String line1,
                                              final String line2) {

        final int l1 = line1.length();
        final int l2 = line2.length();

        final double lenDiffRatio = Math.min(l1, l2) / (double) Math.max(l1, l2); // Results in 1 or less.

        if (lenDiffRatio >= MIN_LENGTH_DIFFERENCE_RATIO) {

            if (l2 < l1) {
                // Compare the other way round.
                if (line1.contains(line2)) {
                    return false;
                }
            } else {
                if (line2.contains(line1)) {
                    return true;
                }
            }

        }

        return null;
    }


    private static List<DumbTokenList> doTheInsaneParsingThing(final File file) {

        final List<DumbTokenList> ret = new ArrayList<>();

        final StringBuilder sb = new StringBuilder();
        try (final InputStream is = new BufferedInputStream(new FileInputStream(file))) {

            final int bufMinus1 = 4;
            final Charset charset = Charset.forName("Cp1252"); // =ansi

            final int[] buf = new int[bufMinus1 + 1]; // "DATA"
            //            while ((buf[buf.length - 1] = is.read()) >= 0) {
            while (true) {

                buf[bufMinus1] = is.read();

                if (buf[bufMinus1] < 0 || (
                        buf[0] == 'D' &&
                                buf[1] == 'A' &&
                                buf[2] == 'T' &&
                                buf[3] == 'A' &&
                                buf[4] == ':')) {

                    if (sb.length() > 0) {
                        ret.add(new DumbTokenList(sb.toString()));
                        sb.setLength(0);
                    }

                    if (buf[bufMinus1] < 0) {
                        break;
                    }

                } else {

                    sb.append(new String(new byte[] { (byte) buf[bufMinus1] }, charset));
                    //                    sb.append((char) buf[bufMinus1]);
                }


                // Shift minibuffer to front.
                for (int i = 0; i < bufMinus1; i++) {
                    buf[i] = buf[i + 1];
                }
            }


        } catch (IOException e) {
            e.printStackTrace();
        }


        // DEDUPLICATE DTLs
        for (int i = ret.size() - 1; i > 0; i--) {

            if (i < ret.size()) {
                final DumbTokenList dtlThis = ret.get(i);
                final int dtlThisTokenCount = dtlThis.tokens.size();

                for (int ii = i - 1; ii >= 0; ii--) {
                    final DumbTokenList dtlThat = ret.get(ii);
                    final int dtlThatTokenCount = dtlThat.tokens.size();


                    int scoreViaRemainingLines_this = dtlThisTokenCount;
                    int scoreViaRemainingLines_that = dtlThatTokenCount;


                    for (int o = 0; o < dtlThisTokenCount; o++) {
                        final String tokenThis = dtlThis.tokens.get(o);
                        for (int oo = 0; oo < dtlThatTokenCount; oo++) {
                            final String tokenThat = dtlThat.tokens.get(oo);

                            final Boolean tooSimilar = areLinesTooSimilar(tokenThis, tokenThat);
                            if (tooSimilar != null) {
                                scoreViaRemainingLines_this--;
                                scoreViaRemainingLines_that--;
                                break;
                            }

                        }
                    }

                    if (scoreViaRemainingLines_this < 0 || scoreViaRemainingLines_that < 0) {
                        throw new Error();
                    }

                    final double scoreActual_this = scoreViaRemainingLines_this / (double) dtlThisTokenCount;
                    final double scoreActual_that = scoreViaRemainingLines_that / (double) dtlThatTokenCount;


                    if (scoreViaRemainingLines_this < scoreViaRemainingLines_that) {
                        if (scoreActual_this < MIN_REMAININGLINES_PERCENTAGEOF_ALLLINES) {
                            final DumbTokenList removed = ret.remove(i);
                            //                            System.err.println("\nREMOVED:\n" + removed + "\nKEPT   :\n" + dtlThat);
                            break; // IMPORTANT.
                        }
                    } else {
                        if (scoreActual_that < MIN_REMAININGLINES_PERCENTAGEOF_ALLLINES) {
                            final DumbTokenList removed = ret.remove(ii);
                            //                            System.err.println("\nREMOVED:\n" + removed + "\nKEPT   :\n" + dtlThis);
                            break; // IMPORTANT.
                        }
                    }


                }

            }
        }

        return ret;
    }


}
Presidente de Dreamspace
fuente
1
Para ejecutar esto, utilicé los siguientes comandos, javac "C:\Users\MLM\Downloads\CrappyChromeNotificationHistoryReader.java"(para compilar), java -cp C:\Users\MLM\Downloads CrappyChromeNotificationHistoryReader(para ejecutar) El script fallaba, if (scoreViaRemainingLines_this < 0 || scoreViaRemainingLines_that < 0) {así que comenté todo el análisis doTheInsaneParsingThingy simplemente imprimí todo System.out.println(sb.toString());cuando el token se agrega a la lista. Parece que "Notificaciones de plataforma" solo maneja las notificaciones push de los trabajadores del servidor.
MLM
@MLM: Gracias por la información de javac. En cuanto al problema: funciona para mí si pego la fuente en un proyecto abierto de Java 8 IntelliJ, pongo mi nombre de usuario (variable "archivo") y ejecuto el código.
Dreamspace Presidente