שיתוף | סקריפט קבלת פודקאסט למייל
-
@שני-אנשים זה מסובך
-
@מתלמד-צעיר
מצאתי את זה
עובד לפי rss עם גוגל שיטס ושומר לדרייב כל פודקאסט בתיקייה נפרדת
לא למדתי js כך שאני לא יודע אם הסקריפט בטוח
ניסיתי את הסקריפט על חשבון אחר, הוספתי את עושים טכנולוגיה וקיבלתי את השגיאה הבאה:
כך שכנראה זה לא עובד לכל הפודקאסטים, אבל אולי אפשר להתבסס על הקוד שם
ניסיתי את זה על עוד כמה פודקאסטים ללא הצלחה [אבל על הפודקאסטים שיש שם זה עובד]
@אביי @מנצפכ אולי תוכלו לעזור בעניין?
עריכה: gpt עזר לי קצתconst PHASES = { INSTALL: 'install', DOWNLOAD: 'download', }; const resumeFrom = PropertiesService.getUserProperties().getProperty('resumeFrom'); const install = () => { if (!resumeFrom || resumeFrom === PHASES.INSTALL) { // Phase 1: Remove existing triggers and create a new trigger ScriptApp.getProjectTriggers().forEach(trigger => ScriptApp.deleteTrigger(trigger)); ScriptApp.newTrigger("podcastManager").timeBased().everyHours(1).create(); // Run once an hour PropertiesService.getUserProperties().setProperty('resumeFrom', PHASES.DOWNLOAD); } if (!resumeFrom || resumeFrom === PHASES.DOWNLOAD) { // Phase 2: Start downloading podcasts podcastManager(); Logger.log("The podcast manager is now running in the background!"); PropertiesService.getUserProperties().deleteProperty('resumeFrom'); // Reset the phase } }; const getLastUpdatedTime = () => { const cacheKey = 'LAST_UPDATED'; const cacheService = CacheService.getUserCache(); const lastUpdatedTime = cacheService.get(cacheKey); cacheService.put(cacheKey, String(Date.now()), 21600); if (lastUpdatedTime) { return new Date(lastUpdatedTime); } const date = new Date(); date.setDate(date.getDate() - 2); return date; }; const getPodcastFolder = (folderName, containerFolder) => { const parentFolder = containerFolder || DriveApp.getRootFolder(); const folders = parentFolder.getFoldersByName(folderName); if (folders.hasNext()) return folders.next(); return parentFolder.createFolder(folderName); }; const parseRSS = (xmlUrl, lastUpdatedTime, includeAll, chapterLimit) => { try { const options = { headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36', }, }; const response = UrlFetchApp.fetch(xmlUrl, options); if (response.getResponseCode() === 200) { const feed = response.getContentText(); const doc = XmlService.parse(feed); const root = doc.getRootElement(); const channel = root.getChild('channel'); let episodes = channel .getChildren('item') .map((item) => { const date = new Date(item.getChildText('pubDate')); const title = item.getChildText('title').replace(/"/g, "'"); const enclosure = item.getChild('enclosure')?.getAttribute("url")?.getValue(); return { date, title, enclosure }; }) .filter(({ enclosure }) => enclosure); if (!includeAll) { // Limit the number of episodes based on the chapterLimit episodes = episodes.slice(0, chapterLimit); } return { title: channel.getChildText('title'), episodes }; } else { console.warn("HTTP error while fetching RSS:", response.getResponseCode()); return { title: "", episodes: [] }; // Return empty data for this feed } } catch (error) { console.error("Error while parsing RSS:", error); return { title: "", episodes: [] }; // Return empty data for this feed } }; const downloadPodcast = (episode, folder, episodeSheet) => { try { if (!episode || !episode.date || !episode.enclosure || !episode.title) { console.warn("Skipping invalid episode:", episode); return; } const { date, enclosure, title } = episode; const cacheKey = `downloaded_${title}`; // Check if the episode has already been downloaded if (CacheService.getUserCache().get(cacheKey)) { console.log("Episode already downloaded:", title); return; } const response = UrlFetchApp.fetch(enclosure); if (response.getResponseCode() === 200) { const blob = response.getBlob(); // Specify the desired file name (use episode title) const fileName = `${title}.mp3`; // You can adjust the file extension if needed const file = folder.createFile(blob.setName(fileName)); // Set the file name episodeSheet.appendRow([new Date(), date, `=HYPERLINK("${enclosure}";"${title}")`, `https://drive.google.com/file/d/${file.getId()}/view`]); // Mark the episode as downloaded in cache CacheService.getUserCache().put(cacheKey, 'downloaded', 21600); // Cache for 6 hours } else { console.warn("Skipping episode due to HTTP error:", response.getResponseCode()); } } catch (error) { console.error("Error while downloading podcast:", error); } }; const getSubscriptions = () => { const ss = SpreadsheetApp.getActiveSpreadsheet(); const sheet = ss.getSheetByName('Subscriptions'); const episodeSheet = ss.getSheetByName('Episodes'); const [header, ...podcasts] = sheet .getDataRange() .getValues() .map(([rss]) => rss) .filter(Boolean); const lastUpdatedTime = getLastUpdatedTime(); const parentFolder = getPodcastFolder('Podcasts'); return { episodeSheet, parentFolder, podcasts, lastUpdatedTime }; }; const podcastManager = () => { const { episodeSheet, parentFolder, podcasts, lastUpdatedTime } = getSubscriptions(); const delayBetweenPodcasts = 1000; // 1 second in milliseconds podcasts.forEach((xmlUrl) => { const includeAll = shouldIncludeAll(xmlUrl); // Determine if "all" should be included based on the XML URL const chapterLimit = getChapterLimit(xmlUrl); // Get the chapter limit from column C based on the XML URL const { title, episodes } = parseRSS(xmlUrl, lastUpdatedTime, includeAll, chapterLimit); if (episodes.length > 0) { const folder = getPodcastFolder(title, parentFolder); episodes.slice(0, chapterLimit).forEach((episode) => { downloadPodcast(episode, folder, episodeSheet); Utilities.sleep(delayBetweenPodcasts); // Add a 1-second delay between podcasts }); } }); }; const shouldIncludeAll = (xmlUrl) => { // You may need to adjust this logic based on the structure of your spreadsheet const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Subscriptions'); const rows = sheet.getDataRange().getValues(); for (const row of rows) { if (row[0] === xmlUrl) { if (row[2] === 'all') { return true; } else if (!isNaN(row[2])) { return false; } } } return false; // Default to false if not found }; const getChapterLimit = (xmlUrl) => { // You may need to adjust this logic based on the structure of your spreadsheet const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Subscriptions'); const rows = sheet.getDataRange().getValues(); for (const row of rows) { if (row[0] === xmlUrl) { if (row[2] === 'all') { return Number.MAX_SAFE_INTEGER; // Download all episodes } else if (!isNaN(row[2])) { return Math.max(1, parseInt(row[2], 10)); // Ensure it's at least 1 } } } return 5; // Default to 5 if not found }; const openPodcast = () => { const cell = SpreadsheetApp.getActiveSheet().getActiveCell().getValue(); if (!/drive.google.com/.test(cell)) { SpreadsheetApp.getActiveSpreadsheet().toast("Please select any podcast drive link in Column D"); return; } const html = `<iframe src="${cell.replace('view', 'preview')}" width="480" height="170" frameborder="0" scrolling="no"></iframe>` const dialog = HtmlService.createHtmlOutput(html).setTitle("Play").setWidth(500).setHeight(200); SpreadsheetApp.getUi().showModelessDialog(dialog, "Play Podcast") } // Run the install function install();
והנה עוד פונקציה שתעבד קובץ opml לשמות וכתובות rss:
function importOPMLFile() { var sheet = SpreadsheetApp.getActiveSheet(); // Prompt the user to upload an OPML file var file = DriveApp.getFileById('YOUR_OPML_FILE_ID_HERE'); // Read the contents of the OPML file var opmlContent = file.getBlob().getDataAsString(); // Parse the OPML content var xmlDoc = XmlService.parse(opmlContent); var opmlRoot = xmlDoc.getRootElement(); // Get all the outline elements (podcast entries) within the OPML file var outlines = opmlRoot.getChildren('body')[0].getChildren('outline'); // Initialize arrays to store RSS addresses and podcast names var rssAddresses = []; var podcastNames = []; // Loop through each outline element for (var i = 0; i < outlines.length; i++) { var outline = outlines[i]; var rssUrl = outline.getAttribute('xmlUrl').getValue(); var podcastName = outline.getAttribute('title').getValue(); // Add the RSS address and podcast name to their respective arrays rssAddresses.push([rssUrl]); podcastNames.push([podcastName]); } // Write the RSS addresses and podcast names to the first two columns of the sheet sheet.getRange(1, 1, rssAddresses.length, 1).setValues(rssAddresses); sheet.getRange(1, 2, podcastNames.length, 1).setValues(podcastNames); }
[צריך להכניס id לקובץ opml שקיים בדרייב]
לא הצלחתי לפצל קבצים מעל 50 מגה
במקרה ומריצים את זה על הרבה פודקאסטים מקבלים אחרי זמן מה את השגיאה הבאה:
Exceeded maximum execution time
[חריגת זמן ריצה מירבי]
ניסיתי לתקן ולא עלתה בידי
יש עוד שגיאות שריצה אחת קיימות ובריצה אחרת לא, כך שמקסימום אם יש שגיאה ניתן להריץ שוב
בברירת מחדל הוא מוריד את ה5 פודקאסטים האחרונים, ניתן לחילופין להכניס בעמודה c מספר אחר, או לכתוב "all"
מי שרוצה לשפץ/לתקן וכו' תע"ב
[ניתן גם להכניס כתובות rss לקול הלשון] -
@האדם-החושב איך אני מוצא RSS של פודקאסט?
-
@שני-אנשים ברוב הפודקאסטים יש סמל כזה:
תלחץ עליו ותעתיק את כתובת הurl, זה כתובת הrss -
@האדם-החושב כתב בשיתוף | סקריפט קבלת פודקאסט למייל:
כך שכנראה זה לא עובד לכל הפודקאסטים, אבל אולי אפשר להתבסס על הקוד שם
אני לא רוצה לפרסם קוד שיעבוד לכל הפודקאסטים
ישנם הרבה שליליים -
פוסט זה נמחק!
-
@מתלמד-צעיר אני יכול, אבל אין לי בזה שום ידע
-
@שני-אנשים @מוגן הסקריפט מוכן!!!
תודה ענקית ל@שמואל5 על העזרה הסופית
סקריפט-קבלת-פודקאסטי-"משפחה"-למיילאם אתם מקבלים תגובה כזו:
פשוט תלחצו "סגירה" ותריצו שוב
אם גם זה לא עוזר נסו לשחק עם הסימונים של פעילות הפודקאסטיםהסקריפט שולב עם "עושים טכנולוגיה"
-
@מתלמד-צעיר תודה על הסקריפט.
הרצתי כעת את הסקריפט ולא קיבלתי שום פרק.
אני אמור לקבל מיידית פרק אחד?
איך אני יכול לדעת אם זה הופעל בצורה תקינה? הרצתי פעמיים.
וכן איך אני יכול לבטל את הסקריפט?
עייינתי ב-docs שהעלית, וכן בקישורים שהבאת, ואין לי מענה על זה. -
@הייתי-שמח-להבין אתה אמור לקבל מייד את כל הפרקים (מכל פודקאסט את האחרון שלו)
אם אתה רוצה לדעת אם הכל תקין תכנס ל>תוספים(בשורה העליונה של השיטס)>Apps Script
תלחץ על "הפעלה" (בשורה העליונה) ותראה מה כתוב למטה בלוג הריצה
כדי לבטל תכנס כנ"ל ובתפריט בצד ימין תכנס למפעילים ותמחק את הטריגר הבודד שמופיע שם
בהצלחה -
@מתלמד-צעיר כתב בשיתוף | סקריפט קבלת פודקאסט למייל:
@הייתי-שמח-להבין אתה אמור לקבל מייד את כל הפרקים (מכל פודקאסט את האחרון שלו)
אם אתה רוצה לדעת אם הכל תקין תכנס ל>תוספים(בשורה העליונה של השיטס)>Apps Script
תלחץ על "הפעלה" (בשורה העליונה) ותראה מה כתוב למטה בלוג הריצה
כדי לבטל תכנס כנ"ל ובתפריט בצד ימין תכנס למפעילים ותמחק את הטריגר הבודד שמופיע שם
בהצלחההסתבכתי, ניסיתי להיכנס דרך התוספים של השיטס והוא לא נותן לי, אני מקבל שגיאה 400, ניסיתי להיכנס ישירות ל-Apps Script, לכאן אני אמור להגיע? או שזה פרויקט אחר, פשוט זה היחיד שיש לי, ולא זכור לי שהרצתי פעם.
-
@הייתי-שמח-להבין לא. אתה לא אמור להגיע לזה
אתה פשוט יצרת פרויקט חדש וריק -
@מתלמד-צעיר כתב בשיתוף | סקריפט קבלת פודקאסט למייל:
@הייתי-שמח-להבין לא. אתה לא אמור להגיע לזה
אתה פשוט יצרת פרויקט חדש וריקאז להתקין שוב?!
כשאני מנסה להתקין הוא מבקש ממני הרשאה משום מה מפרופיל אחר שיש לי על המחשב, ואני מאשר לו, אולי זה הבעיה? -
@מתלמד-צעיר הנה באמת אני רואה שהוא שם לי את זה על הפרופיל השני, אני לא מצליח להבין למה זה קורה, אני נמצא בתוך הפרופיל שלי ולוחץ על "יצירת עותק" ואז אוטומטית הוא מביא אותי לפרופיל אחר שעל המחשב ומתקין את הכל שם, ניסיתי מלא פעמים.
-
@הייתי-שמח-להבין תכנס שוב למסך ששואל אותך האם ליצור עותק ואז בשורת הדפדפן תשנה את המילה copy ל-edit ותלחץ אנטר ואז בצד שמאל למעלה תחליף לפרופיל שלך ולאחר מכן בשורה העליונה בתפריט קובץ תבחר ב"צור עותק"
-
@מתלמד-צעיר כתב בשיתוף | סקריפט קבלת פודקאסט למייל:
@הייתי-שמח-להבין תכנס שוב למסך ששואל אותך האם ליצור עותק ואז בשורת הדפדפן תשנה את המילה copy ל-edit ותלחץ אנטר ואז בצד שמאל למעלה תחליף לפרופיל שלך ולאחר מכן בשורה העליונה בתפריט קובץ תבחר ב"צור עותק"
תודה רבה הנה זה באמת הולך.
אך בינתיים כחמש דקות אחרי עדיין לא קיבלתי שום מייל. -
@הייתי-שמח-להבין כשהוא ביקש הרשאה הוא נכנס לחשבון שלך?
-
יישר כוח עצום על הסקריפט!
אשמח לדעת אם אפשר לקבל גם את הפודקאסטים הקודמים? -
-
@מתלמד-צעיר הנה עכשיו נכנסתי לפרויקט ב-Apps Script ועשיתי הפעלה כמו שהסברת למעלה, והכל הסתדר, קיבלתי ישר את הפרק האחרון.
עכשיו יש לי את אותה בעיה עם קבלת העלון של הידברות שנתת קישור ב-DOCS, שהוא עובר לפרופיל השני, את מה לשנות שם?
ממש תודה לך, זה ממש מוצלח הסקריפט שלך.