Existe alguma maneira de visualizar o histórico de notificações do navegador Chrome?

57

Recebo notificações do Chrome de vários sites e eles funcionam quando nem sequer tenho nenhuma guia aberta para esses sites.

Mas às vezes recebo essas notificações do Chrome quando não estou na minha mesa ou no meu laptop.

Como algumas dessas notificações são úteis para mim, eu gostaria de poder acessar as que perdi.

Existe uma maneira de visualizar o histórico de notificações?

paradroid
fonte
1
Não parece. Observando esta postagem ( theverge.com/2015/10/14/9531133/… ), eles reorganizaram sua política de notificação e a removeram da área de trabalho para colocá-la em páginas da web individuais. A única coisa para acessar novas notificações é clicar na campainha em uma página do google.
Terry
1
Parece que não: productforums.google.com/forum/#!msg/chrome/xs9PflHTfho/… - muito lamentável.
LB--
O único lugar em que encontrei as notificações como uma lista é se o site que as aciona as possui pelo site. O Chrome não parece coletá-los em algo parecido chrome://notificationse eles não chegam ao sistema operacional.
Jason Lydon
Aceite o @paradroid resposta válida
Satheesh

Respostas:

31

Se você tem um Mac, existe uma maneira! 😄

Veja como seria a lista de notificações:

Veja como seria a lista de notificações.

Tudo o que você precisa fazer é:

1. No chrome, acesse:

chrome://flags/

2. Procure por:

Enable native notifications. Mac

3. Habilite, reinicie o chrome, está pronto. Desfrutar!

EDITAR:

  • Talvez você não precise mais fazer o que precede.

A partir do Chrome 59, as notificações enviadas pela API de Notificações ou pela API de extensões chrome.notifications serão mostradas diretamente pelo sistema de notificação nativo do macOS, em vez do sistema do Chrome. [ fonte ]

Esdras Lopez
fonte
2
Isso não responde à questão de ver o histórico de notificações, apenas ver as notificações.
Bjorn
6
@BjornTipling Ele responde. Ele está perguntando se pode ver as notificações que perdeu enquanto estiver fora e meu método faz exatamente isso.
Esdras Lopez 15/03
1
Se você colocar os links como comentários, eu vou adicioná-los à sua mensagem para você, @EsdrasLopez
user418150
1
@ user418150 Aprecio isso, mas agora tenho reputação. :) Verifique as edições.
Esdras Lopez
2
O principal problema aqui é que ele só armazena a notificação se você não clicar nela. Várias vezes eu cliquei em um título interessante do artigo, apenas para não carregar, no entanto, ele ainda foi removido da lista de notificações. Geralmente, os artigos são novos demais para serem pesquisados ​​no Google e, muitas vezes, o título da notificação não corresponde ao título do artigo, por isso se perde nas entranhas da Web.
iBorg 21/09
13

No MacOSX, você terá o diretório Chrome localizado na Biblioteca / Suporte ao aplicativo. Abra o aplicativo de terminal e execute os próximos comandos:

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

Agora você verá arquivos 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

Você pode ver que o mais recente é 000003.log, portanto, verifique-o pelo próximo comando:

tail -n 100 000003.log

E você verá os últimos 100 itens desse log. Em seguida, você pode abrir as configurações do Chrome e desativar a notificação do site.

Observe que se você possui vários perfis no chrome, seu caminho pode ser diferente, assim (Profile1 em vez de Default):

cd ~/Library/Application\ Support/Google/Chrome/Profile\ 1/Platform\ Notifications/
Andrey Bezpalenko
fonte
3
Essa deve ser a resposta aceita. :)
Cody A. Ray
1
Ainda trabalhando em 2019 (embora o registro precise de um pouco de interpretação). Ótima resposta obrigado
carpii 23/06
12

Se você for para %LocalAppData%\Google\Chrome\User Data\Default\Platform Notifications, há um arquivo de log de notificações anteriores.

Corey
fonte
4
bom, mas considere especificar o caminho como "% LocalAppData% \ Google \ Chrome \ Dados do usuário \ Padrão \ Notificações de plataforma" em vez de código rígido. Funciona perfeitamente em qualquer PC.
Dmitry Gusarov
Na pasta UserData /, talvez seja necessário localizar primeiro a pasta do perfil, como "C: \ Usuários \ nome de usuário \ AppData \ Local \ Google \ Chrome \ UserData \ Perfil 1 \ Notificações de Plataforma"
Maffelu
1
Esses dados são binários. Como lê-lo?
Gaia
No Chrome 71, e o arquivo de log está vazio. Isso foi desativado em algum momento?
James
3
@ Gaia Eu me perguntava a mesma coisa e acabei de criar um código Java de baixa qualidade que faz um trabalho aceitável em decifrar a maior parte dele. Publiquei abaixo: superuser.com/a/1410742/778383
Dreamspace President
3

Como não parece possível obter um registro das notificações diretamente, se eu tivesse o mesmo problema, trapacearia usando um emulador de telefone Android, ou um telefone, como o usuário que recomendou o Pushbullet. Mas não há apenas o Pushbullet, há muitos outros aplicativos; poderíamos discutir os truques do Android para ouvir e gravar notificações, em um tópico separado.

Se você é um programador, talvez possa resolver seu problema usando uma extensão caseira:

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

"Você pode conectar a função webkitNotifications.createNotification para que sempre que uma notificação seja criada, você execute algum código específico."

Quidam
fonte
2

Tocando em algo que foi mencionado um pouco acima, mas com uma reviravolta que garante que você não perca a notificação no OSX:

  1. No lado direito da barra superior principal, clique no ícone de notificação.

  2. Clique na roda dentada (canto inferior direito da tela de notificação)

  3. Selecione Chrome para configurar como as notificações são exibidas.

  4. Por padrão, "Banners" são selecionados e podem desaparecer automaticamente. Em vez disso, selecione o tipo "Alerta" e eles permanecerão lá enquanto você não os reconhecer!

Você é bem vindo :)

Patrick St-Onge
fonte
2

Você pode ver o histórico das notificações por push. No canto inferior direito da tela do seu PC, na barra de tarefas, está o que parece um balão de fala e, se você passar o mouse sobre ele, verá que ele é realmente chamado de "notificações". Se você clicar nesse balão, ele exibirá seus e-mails não lidos / novos e todas as notificações por push que você não dispensou. Eu vim aqui procurando por esta resposta e não a encontrei, mas depois consegui resolver isso. Estou usando o Windows 10.

Shea Bethell
fonte
Sim, isso é algo recente no Win10, mas é a resposta final para o Windows.
Paradroid
-1

Parece que o Pushbullet pode resolver seu problema. Eles afirmam que você pode ver as notificações perdidas usando a extensão do Chrome.

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

Socialorganix Contentbrandmgmt
fonte
Leia Como recomendar software para obter as informações mínimas necessárias e sugestões sobre como recomendar software para Superusuário. Para manter sua resposta útil, mesmo se o (s) link (s) fornecido (s) quebrar esses detalhes, deve ser editado em sua resposta.
Eu digo Restabelecer Monica
Ei, legal. Eu vou tentar isso. Na verdade, eu já uso o Pushbullet, mas não tinha conhecimento dessa extensão do Chrome.
Paradroid
Não consigo encontrar esse recurso. Uma notificação apareceu e não há vestígios dela no histórico da notificação.
Madprops 14/09/16
Repensei a questão e o problema é esse. Se o seu telefone receber uma notificação, o pushbullet o entregará na área de trabalho e informará que você tem notificações possivelmente não lidas (você pode ter visto no seu telefone ou no que você tem). Para quais sites você está recebendo notificações do Google Chrome? Se houver um aplicativo para ele, você sempre poderá instalá-lo e receberá as notificações do pushbullet no seu desktop / laptop / o que for.
Socialorganix Contentbrandmgmt 15/09/16
1
O recurso "Notificações" no Pushbullet é apenas para ver notificações do seu telefone Android na área de trabalho e o mesmo no iPhone se você tiver uma área de trabalho Mac. Não tem nada a ver com as notificações do Chrome.
Boaz
-1

Graças ao Corey 's resposta acima, e um sábado preguiçoso com muito tempo em minhas mãos, eu posso ver agora uma lista de notificações do Chrome recentes na consola do meu IDE, onde eu ainda pode clicar nos URLs.

O código é ruim e usa heurísticas brutas, pois não tenho idéia da maneira correta de interpretar os dados binários.

Mas é muito melhor que nada. Exemplo de saída (trecho):

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 crucificação:

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 da Dreamspace
fonte
1
Para executar essa operação, usei os seguintes comandos javac "C:\Users\MLM\Downloads\CrappyChromeNotificationHistoryReader.java"(para compilar), java -cp C:\Users\MLM\Downloads CrappyChromeNotificationHistoryReader(para executar) O script estava falhando, por if (scoreViaRemainingLines_this < 0 || scoreViaRemainingLines_that < 0) {isso comentei todas as análises doTheInsaneParsingThinge apenas imprimi tudo System.out.println(sb.toString());quando o token foi adicionado à lista. Parece que "Notificações de plataforma" lida apenas com as notificações por push do trabalhador do servidor.
MLM
@MLM: Obrigado pela informação javac. Quanto ao problema: Funciona para mim se eu colar a fonte em um projeto Java 8 IntelliJ aberto, colocar meu nome de usuário (variável "file") e executar o código.
Dreamspace President