דילוג לתוכן
  • חוקי הפורום
  • פופולרי
  • לא נפתר
  • משתמשים
  • חיפוש גוגל בפורום
  • צור קשר
עיצובים
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • ברירת מחדל (ללא עיצוב (ברירת מחדל))
  • ללא עיצוב (ברירת מחדל)
כיווץ
מתמחים טופ
  1. דף הבית
  2. מחשבים וטכנולוגיה
  3. עזרה הדדית - מחשבים וטכנולוגיה
  4. המלצה | תוסף להורדת הודעות אודיו בגוגל צ'אט

המלצה | תוסף להורדת הודעות אודיו בגוגל צ'אט

מתוזמן נעוץ נעול הועבר עזרה הדדית - מחשבים וטכנולוגיה
4 פוסטים 2 כותבים 28 צפיות 2 עוקבים
  • מהישן לחדש
  • מהחדש לישן
  • הכי הרבה הצבעות
תגובה
  • תגובה כנושא
התחברו כדי לפרסם תגובה
נושא זה נמחק. רק משתמשים עם הרשאות מתאימות יוכלו לצפות בו.
  • ר מחובר
    ר מחובר
    רפי סאם
    כתב נערך לאחרונה על ידי
    #1

    לבקשת @מים-אחרונים
    יצרתי תוסף להורדת הודעות אודיו מגוגל צ'אט
    אם יש שיפורים או בקשות לעוד תוספים שלחו כאן בקשה
    או במייל שבפרופיל...
    תוסף להורדת אודיו מגוגל צ'אט.zip


    3aafff0d-99a0-4a65-aefd-245ae6977884-image.png

    ר תגובה 1 תגובה אחרונה
    3
    • ר רפי סאם התייחס לנושא זה
    • ר רפי סאם

      לבקשת @מים-אחרונים
      יצרתי תוסף להורדת הודעות אודיו מגוגל צ'אט
      אם יש שיפורים או בקשות לעוד תוספים שלחו כאן בקשה
      או במייל שבפרופיל...
      תוסף להורדת אודיו מגוגל צ'אט.zip


      3aafff0d-99a0-4a65-aefd-245ae6977884-image.png

      ר מחובר
      ר מחובר
      רפי סאם
      כתב נערך לאחרונה על ידי
      #2

      לכל המעוניין
      הנה קוד לטפרמונקי

      // @name         GChat Audio Download
      // @namespace    https://chat.google.com/
      // @version      1.0
      // @description  מוסיף כפתור הורדה להודעות שמע ב-Google Chat
      // @author       You
      // @match        https://chat.google.com/*
      // @grant        none
      // @run-at       document-idle
      // ==/UserScript==
      
      (() => {
        const DONE = 'gchat-dl-done';
      
        function makeBtn(url) {
          const b = document.createElement('button');
          b.textContent = '⬇ הורד שמע';
          b.style.cssText = `
            all: initial;
            display: block !important;
            margin: 4px 8px 6px 8px !important;
            padding: 4px 16px !important;
            background: #1a73e8 !important;
            color: white !important;
            border: none !important;
            border-radius: 20px !important;
            font: 500 12px "Google Sans",Arial,sans-serif !important;
            cursor: pointer !important;
            direction: rtl !important;
            box-sizing: border-box !important;
          `;
          b.onmouseenter = () => b.style.setProperty('background', '#1557b0', 'important');
          b.onmouseleave = () => b.style.setProperty('background', '#1a73e8', 'important');
          b.onclick = async (e) => {
            e.stopPropagation(); e.preventDefault();
            b.textContent = '⏳ מוריד…';
            b.style.setProperty('background', '#f9ab00', 'important');
            b.style.setProperty('color', '#000', 'important');
            try {
              const r = await fetch(url, { credentials: 'include' });
              if (!r.ok) throw new Error(r.status);
              const blob = await r.blob();
              const ext = blob.type.includes('ogg') ? 'ogg'
                        : blob.type.includes('webm') ? 'webm'
                        : blob.type.includes('wav') ? 'wav' : 'mp3';
              const a = document.createElement('a');
              a.href = URL.createObjectURL(blob);
              a.download = `gchat-${Date.now()}.${ext}`;
              document.body.appendChild(a); a.click();
              setTimeout(() => { document.body.removeChild(a); URL.revokeObjectURL(a.href); }, 9000);
              b.textContent = '✓ הורד!';
              b.style.setProperty('background', '#34a853', 'important');
              b.style.setProperty('color', 'white', 'important');
              setTimeout(() => {
                b.textContent = '⬇ הורד שמע';
                b.style.setProperty('background', '#1a73e8', 'important');
                b.style.setProperty('color', 'white', 'important');
              }, 3000);
            } catch(err) {
              b.textContent = '✗ שגיאה';
              b.style.setProperty('background', '#ea4335', 'important');
              b.style.setProperty('color', 'white', 'important');
              setTimeout(() => {
                b.textContent = '⬇ הורד שמע';
                b.style.setProperty('background', '#1a73e8', 'important');
                b.style.setProperty('color', 'white', 'important');
              }, 3000);
            }
          };
          return b;
        }
      
        function tryInject(el) {
          if (!(el instanceof Element)) return;
          if (el.hasAttribute(DONE)) return;
          const url = el.getAttribute('data-media-url');
          if (!url || !url.includes('get_attachment_url')) return;
          el.setAttribute(DONE, '1');
          const parent = el.closest('.DwygBd') || el.parentElement;
          if (parent) {
            parent.appendChild(makeBtn(url));
            console.log('[DL] ✅ injected');
          }
        }
      
        function scan() {
          document.querySelectorAll('[data-media-url]').forEach(tryInject);
        }
      
        new MutationObserver(muts => {
          for (const m of muts) {
            for (const n of m.addedNodes) {
              if (n.nodeType !== 1) continue;
              tryInject(n);
              n.querySelectorAll?.('[data-media-url]').forEach(tryInject);
            }
            if (m.type === 'attributes' && m.target instanceof Element) {
              tryInject(m.target);
            }
          }
        }).observe(document.documentElement, {
          childList: true, subtree: true,
          attributes: true, attributeFilter: ['data-media-url']
        });
      
        [0, 500, 1000, 2000, 4000, 8000].forEach(t => setTimeout(scan, t));
      })();
      בנימין מחשביםב תגובה 1 תגובה אחרונה
      1
      • ר רפי סאם התייחס לנושא זה
      • ר רפי סאם

        לכל המעוניין
        הנה קוד לטפרמונקי

        // @name         GChat Audio Download
        // @namespace    https://chat.google.com/
        // @version      1.0
        // @description  מוסיף כפתור הורדה להודעות שמע ב-Google Chat
        // @author       You
        // @match        https://chat.google.com/*
        // @grant        none
        // @run-at       document-idle
        // ==/UserScript==
        
        (() => {
          const DONE = 'gchat-dl-done';
        
          function makeBtn(url) {
            const b = document.createElement('button');
            b.textContent = '⬇ הורד שמע';
            b.style.cssText = `
              all: initial;
              display: block !important;
              margin: 4px 8px 6px 8px !important;
              padding: 4px 16px !important;
              background: #1a73e8 !important;
              color: white !important;
              border: none !important;
              border-radius: 20px !important;
              font: 500 12px "Google Sans",Arial,sans-serif !important;
              cursor: pointer !important;
              direction: rtl !important;
              box-sizing: border-box !important;
            `;
            b.onmouseenter = () => b.style.setProperty('background', '#1557b0', 'important');
            b.onmouseleave = () => b.style.setProperty('background', '#1a73e8', 'important');
            b.onclick = async (e) => {
              e.stopPropagation(); e.preventDefault();
              b.textContent = '⏳ מוריד…';
              b.style.setProperty('background', '#f9ab00', 'important');
              b.style.setProperty('color', '#000', 'important');
              try {
                const r = await fetch(url, { credentials: 'include' });
                if (!r.ok) throw new Error(r.status);
                const blob = await r.blob();
                const ext = blob.type.includes('ogg') ? 'ogg'
                          : blob.type.includes('webm') ? 'webm'
                          : blob.type.includes('wav') ? 'wav' : 'mp3';
                const a = document.createElement('a');
                a.href = URL.createObjectURL(blob);
                a.download = `gchat-${Date.now()}.${ext}`;
                document.body.appendChild(a); a.click();
                setTimeout(() => { document.body.removeChild(a); URL.revokeObjectURL(a.href); }, 9000);
                b.textContent = '✓ הורד!';
                b.style.setProperty('background', '#34a853', 'important');
                b.style.setProperty('color', 'white', 'important');
                setTimeout(() => {
                  b.textContent = '⬇ הורד שמע';
                  b.style.setProperty('background', '#1a73e8', 'important');
                  b.style.setProperty('color', 'white', 'important');
                }, 3000);
              } catch(err) {
                b.textContent = '✗ שגיאה';
                b.style.setProperty('background', '#ea4335', 'important');
                b.style.setProperty('color', 'white', 'important');
                setTimeout(() => {
                  b.textContent = '⬇ הורד שמע';
                  b.style.setProperty('background', '#1a73e8', 'important');
                  b.style.setProperty('color', 'white', 'important');
                }, 3000);
              }
            };
            return b;
          }
        
          function tryInject(el) {
            if (!(el instanceof Element)) return;
            if (el.hasAttribute(DONE)) return;
            const url = el.getAttribute('data-media-url');
            if (!url || !url.includes('get_attachment_url')) return;
            el.setAttribute(DONE, '1');
            const parent = el.closest('.DwygBd') || el.parentElement;
            if (parent) {
              parent.appendChild(makeBtn(url));
              console.log('[DL] ✅ injected');
            }
          }
        
          function scan() {
            document.querySelectorAll('[data-media-url]').forEach(tryInject);
          }
        
          new MutationObserver(muts => {
            for (const m of muts) {
              for (const n of m.addedNodes) {
                if (n.nodeType !== 1) continue;
                tryInject(n);
                n.querySelectorAll?.('[data-media-url]').forEach(tryInject);
              }
              if (m.type === 'attributes' && m.target instanceof Element) {
                tryInject(m.target);
              }
            }
          }).observe(document.documentElement, {
            childList: true, subtree: true,
            attributes: true, attributeFilter: ['data-media-url']
          });
        
          [0, 500, 1000, 2000, 4000, 8000].forEach(t => setTimeout(scan, t));
        })();
        בנימין מחשביםב מנותק
        בנימין מחשביםב מנותק
        בנימין מחשבים
        כתב נערך לאחרונה על ידי
        #3

        @רפי-סאם כתב בהמלצה | תוסף להורדת הודעות אודיו בגוגל צ'אט:

        קוד לטפרמונקי

        מישהו ניסה?
        כי ג'יימיני טוען שזה לא יעבוד (כאילו אפשר לסמוך עליו בזה... 🙄)

        "הקוד שכתבת נראה כמו ניסיון יפה "לדוג" את קבצי השמע מתוך הממשק של Google Chat, אבל ב-Google כמו ב-Google, העניינים קצת יותר מורכבים מסריקה פשוטה של ה-DOM. יש כמה סיבות טכניות למה הקוד הזה כנראה לא יספק את הסחורה:

        1. בעיית ה-Selector והמבנה הדינמי
          הסתמכת על ה-Attribute בשם data-media-url. גוגל משנה לעיתים קרובות את שמות המחלקות (Classes) והמאפיינים של האלמנטים שלהם. אם המאפיין הזה לא קיים בדיוק בשם הזה על האלמנט שחיפשת, ה-MutationObserver וה-querySelectorAll פשוט לא ימצאו כלום.

        2. הזרקה ל-Shadow DOM (אולי)
          חלק מהרכיבים החדשים ביישומי Google משתמשים ב-Shadow DOM. אם נגן השמע נמצא בתוך Shadow Root, ה-document.querySelectorAll הרגיל שלך לא "רואה" אותו, ולכן לא יכול להזריק את הכפתור.

        3. מדיניות אבטחה (CORS & CSP)
          גם אם הצלחת להזריק את הכפתור, הפקודה fetch(url) כנראה תיחסם:

        CSP (Content Security Policy): גוגל מגבילה לעיתים קרובות מאיזה מקורות מותר להוריד נתונים בדף.

        CORS: השרת שמארח את קבצי השמע (לרוב googleusercontent.com) עשוי לא לאפשר בקשות Fetch ישירות מהסקריפט ללא הגדרות מתאימות.

        1. זיהוי האלמנט הלא נכון
          השתמשת ב-.closest('.DwygBd'). השם DwygBd הוא שם מחלקה מעורבל (obfuscated). שמות כאלו משתנים בכל עדכון גרסה של Google Chat. ברגע שהם מעדכנים גרסה, הסקריפט שלך הופך להיסטוריה.

        מה אפשר לעשות?
        כדי שזה יעבוד באמת, כדאי לשנות גישה:

        זיהוי גנרי יותר: במקום לחפש data-media-url, חפש אלמנטים של audio או source בתוך הודעות, או אלמנטים עם role="button" שיש להם טקסט או תיאור שקשור להשמעה.

        שימוש ב-GM_xmlhttpRequest: אם אתה משתמש ב-Tampermonkey, כדאי להשתמש ב-GM_xmlhttpRequest (במקום fetch) כדי לעקוף מגבלות CORS.

        בדיקת ה-Network: לפעמים ה-URL של השמע נוצר רק ברגע שלוחצים על Play. במקרה כזה, הסקריפט שלך שמחפש בטעינה ראשונית לא ימצא כלום.

        תרצה שאנסה לעזור לך למצוא סלקטור (Selector) יותר יציב או לכתוב פונקציה שתעקוף את בעיית ה-CORS?"

        ר תגובה 1 תגובה אחרונה
        0
        • בנימין מחשביםב בנימין מחשבים

          @רפי-סאם כתב בהמלצה | תוסף להורדת הודעות אודיו בגוגל צ'אט:

          קוד לטפרמונקי

          מישהו ניסה?
          כי ג'יימיני טוען שזה לא יעבוד (כאילו אפשר לסמוך עליו בזה... 🙄)

          "הקוד שכתבת נראה כמו ניסיון יפה "לדוג" את קבצי השמע מתוך הממשק של Google Chat, אבל ב-Google כמו ב-Google, העניינים קצת יותר מורכבים מסריקה פשוטה של ה-DOM. יש כמה סיבות טכניות למה הקוד הזה כנראה לא יספק את הסחורה:

          1. בעיית ה-Selector והמבנה הדינמי
            הסתמכת על ה-Attribute בשם data-media-url. גוגל משנה לעיתים קרובות את שמות המחלקות (Classes) והמאפיינים של האלמנטים שלהם. אם המאפיין הזה לא קיים בדיוק בשם הזה על האלמנט שחיפשת, ה-MutationObserver וה-querySelectorAll פשוט לא ימצאו כלום.

          2. הזרקה ל-Shadow DOM (אולי)
            חלק מהרכיבים החדשים ביישומי Google משתמשים ב-Shadow DOM. אם נגן השמע נמצא בתוך Shadow Root, ה-document.querySelectorAll הרגיל שלך לא "רואה" אותו, ולכן לא יכול להזריק את הכפתור.

          3. מדיניות אבטחה (CORS & CSP)
            גם אם הצלחת להזריק את הכפתור, הפקודה fetch(url) כנראה תיחסם:

          CSP (Content Security Policy): גוגל מגבילה לעיתים קרובות מאיזה מקורות מותר להוריד נתונים בדף.

          CORS: השרת שמארח את קבצי השמע (לרוב googleusercontent.com) עשוי לא לאפשר בקשות Fetch ישירות מהסקריפט ללא הגדרות מתאימות.

          1. זיהוי האלמנט הלא נכון
            השתמשת ב-.closest('.DwygBd'). השם DwygBd הוא שם מחלקה מעורבל (obfuscated). שמות כאלו משתנים בכל עדכון גרסה של Google Chat. ברגע שהם מעדכנים גרסה, הסקריפט שלך הופך להיסטוריה.

          מה אפשר לעשות?
          כדי שזה יעבוד באמת, כדאי לשנות גישה:

          זיהוי גנרי יותר: במקום לחפש data-media-url, חפש אלמנטים של audio או source בתוך הודעות, או אלמנטים עם role="button" שיש להם טקסט או תיאור שקשור להשמעה.

          שימוש ב-GM_xmlhttpRequest: אם אתה משתמש ב-Tampermonkey, כדאי להשתמש ב-GM_xmlhttpRequest (במקום fetch) כדי לעקוף מגבלות CORS.

          בדיקת ה-Network: לפעמים ה-URL של השמע נוצר רק ברגע שלוחצים על Play. במקרה כזה, הסקריפט שלך שמחפש בטעינה ראשונית לא ימצא כלום.

          תרצה שאנסה לעזור לך למצוא סלקטור (Selector) יותר יציב או לכתוב פונקציה שתעקוף את בעיית ה-CORS?"

          ר מחובר
          ר מחובר
          רפי סאם
          כתב נערך לאחרונה על ידי
          #4

          @בנימין-מחשבים התוסף עובד לי
          מה שג'ימיני אומר זה חרתא
          זה סה"כ שולף את הקישור שכבר קיים ופותח אותו בכרטיסייה חדשה

          הטפרמונקי לא נוסה על ידי...

          תגובה 1 תגובה אחרונה
          0
          • יאיר דניאלי יאיר דניאל התייחס לנושא זה

          • התחברות

          • אין לך חשבון עדיין? הרשמה

          • התחברו או הירשמו כדי לחפש.
          • פוסט ראשון
            פוסט אחרון
          0
          • חוקי הפורום
          • פופולרי
          • לא נפתר
          • משתמשים
          • חיפוש גוגל בפורום
          • צור קשר