def album(self): page = requests.get(self.url, headers=self.header) soup = BeautifulSoup(page.content, "lxml") # 初始化 self.podcast = Podcast() self.podcast.name = soup.find('div', 'detailContent_title').get_text() self.podcast.authors.append(Person("Powered by forecho", '*****@*****.**')) self.podcast.website = self.url self.podcast.copyright = 'cc-by' self.podcast.description = soup.find('div', 'mid_intro').get_text() self.podcast.language = 'cn' self.podcast.image = soup.find('a', 'albumface180').find('img').get('src').split('!')[0] self.podcast.feed_url = 'http://podcast.forecho.com/ximalaya/%s.rss' % self.album_id self.podcast.category = Category('Technology', 'Podcasting') self.podcast.explicit = False self.podcast.complete = False self.podcast.owner = Person("forecho", '*****@*****.**') sound_ids = soup.find('div', class_='personal_body').get('sound_ids').split(',') for sound_id in sound_ids: date = soup.find('li', sound_id=sound_id).find('div', class_='operate').get_text().strip() self.detail(sound_id, date) # 生成文件 # print self.podcast.rss_str() self.podcast.rss_file('ximalaya/%s.rss' % self.album_id, minimize=True)
def test_immutable(self): c = Category("Arts", "Food") self.assertRaises(AttributeError, setattr, c, "category", "Technology") self.assertEqual(c.category, "Arts") self.assertRaises(AttributeError, setattr, c, "subcategory", "Design") self.assertEqual(c.subcategory, "Food")
def album(self): album_info_content = requests.get(self.album_info_api).content album_info_data = json.loads(album_info_content) album_list_content = requests.get(self.album_list_api).content album_list_data = json.loads(album_list_content) self.podcast = Podcast() self.podcast.name = album_info_data['data']['title'] self.podcast.authors.append(Person("Powered by maijver", '*****@*****.**')) self.podcast.website = self.url self.podcast.copyright = 'cc-by' self.podcast.description = album_info_data['data']['description'] self.podcast.language = 'cn' self.podcast.image = album_info_data['data']['thumbs']['small_thumb'].replace('!200', '') self.podcast.feed_url = 'http://podcast.forecho.com/qingting/%s.rss' % self.album_id self.podcast.category = Category('Technology', 'Podcasting') self.podcast.explicit = False self.podcast.complete = False self.podcast.owner = Person("maijver", '*****@*****.**') for each in album_list_data['data']: episode = self.podcast.add_episode() episode.id = str(each['id']) episode.title = each['title'] print(self.podcast.name + '=====' + each['title']) episode.image = album_info_data['data']['thumbs']['small_thumb'].replace('!200', '') episode.summary = each['title'] episode.link = 'http://www.qingting.fm/channels/{}/programs/{}'.format(self.album_id, each['id']) episode.authors = [Person("forecho", '*****@*****.**')] episode.publication_date = self.reduction_time(each['update_time']) episode.media = Media("http://od.qingting.fm/{}".format(each['mediainfo']['bitrates_url'][0]['file_path']), each['duration']) self.podcast.rss_file('qingting/{}.rss'.format(self.album_id), minimize=True)
def populate(self, show) -> None: self._set_if_false(show, 'description', self.settings.get('description')) default_category = Category( **self.settings['category']) if self.settings.get( 'category') else None self._set_if_false(show, 'category', default_category) self._set_if_false(show, 'language', self.settings.get('language')) self._set_if_false(show, 'website', self.settings.get('website')) self._set_if_false( show, 'authors', [Person(**author) for author in self.settings['authors']] if self.settings.get('authors') else []) default_webmaster = Person( **self.settings['web_master']) if self.settings.get( 'web_master') else None self._set_if_false(show, 'web_master', default_webmaster) self._set_if_none(show, 'explicit', self.settings.get('explicit')) default_owner = Person( **self.settings['owner']) if self.settings.get('owner') else None self._set_if_false(show, 'owner', default_owner) if show.owner: self._set_if_false(show, 'copyright', show.owner.name) self._set_if_false(show, 'image', self.settings.get('image'))
def main(): """Create an example podcast and print it or save it to a file.""" # There must be exactly one argument, and it is must end with rss if len(sys.argv) != 2 or not ( sys.argv[1].endswith('rss')): # Invalid usage, print help message # print_enc is just a custom function which functions like print, # except it deals with byte arrays properly. print_enc ('Usage: %s ( <file>.rss | rss )' % \ 'python -m podgen') print_enc ('') print_enc (' rss -- Generate RSS test output and print it to stdout.') print_enc (' <file>.rss -- Generate RSS test teed and write it to file.rss.') print_enc ('') exit() # Remember what type of feed the user wants arg = sys.argv[1] from podgen import Podcast, Person, Media, Category, htmlencode # Initialize the feed p = Podcast() p.name = 'Testfeed' p.authors.append(Person("Lars Kiesow", "*****@*****.**")) p.website = 'http://example.com' p.copyright = 'cc-by' p.description = 'This is a cool feed!' p.language = 'de' p.feed_url = 'http://example.com/feeds/myfeed.rss' p.category = Category('Technology', 'Podcasting') p.explicit = False p.complete = False p.new_feed_url = 'http://example.com/new-feed.rss' p.owner = Person('John Doe', '*****@*****.**') p.xslt = "http://example.com/stylesheet.xsl" e1 = p.add_episode() e1.id = 'http://lernfunk.de/_MEDIAID_123#1' e1.title = 'First Element' e1.summary = htmlencode('''Lorem ipsum dolor sit amet, consectetur adipiscing elit. Tamen aberramus a proposito, et, ne longius, prorsus, inquam, Piso, si ista mala sunt, placet. Aut etiam, ut vestitum, sic sententiam habeas aliam domesticam, aliam forensem, ut in fronte ostentatio sit, intus veritas occultetur? Cum id fugiunt, re eadem defendunt, quae Peripatetici, verba <3.''') e1.link = 'http://example.com' e1.authors = [Person('Lars Kiesow', '*****@*****.**')] e1.publication_date = datetime.datetime(2014, 5, 17, 13, 37, 10, tzinfo=pytz.utc) e1.media = Media("http://example.com/episodes/loremipsum.mp3", 454599964, duration= datetime.timedelta(hours=1, minutes=32, seconds=19)) # Should we just print out, or write to file? if arg == 'rss': # Print print_enc(p.rss_str()) elif arg.endswith('rss'): # Write to file p.rss_file(arg, minimize=True)
def test_immutable(self): c = Category("Arts", "Food") self.assertRaises(AttributeError, setattr, c, "category", "Fiction") self.assertEqual(c.category, "Arts") self.assertRaises(AttributeError, setattr, c, "subcategory", "Science Fiction") self.assertEqual(c.subcategory, "Food")
def album(self): page = requests.get(self.album_url, headers=self.header) soup = BeautifulSoup(page.content, "lxml") # 初始化 self.podcast = Podcast() self.podcast.name = soup.find('h1', 'title').get_text() self.podcast.authors.append(Person("Powered by forecho", '*****@*****.**')) self.podcast.website = self.album_url self.podcast.copyright = 'cc-by' if soup.find('div', 'album-intro') and soup.find('div', 'album-intro').get_text(): self.podcast.description = soup.find('div', 'album-intro').get_text() else: self.podcast.description = self.podcast.name self.podcast.language = 'cn' self.podcast.image = soup.find('div', 'album-info').find('img').get('src').split('!')[0] self.podcast.feed_url = 'http://podcast.forecho.com/ximalaya/%s.rss' % self.album_id self.podcast.category = Category('Technology', 'Podcasting') self.podcast.explicit = False self.podcast.complete = False self.podcast.owner = Person("forecho", '*****@*****.**') album_list_content = requests.get(self.album_list_api, headers=self.header).content album_list_data = json.loads(album_list_content.decode('utf-8')) count = len(album_list_data['data']['tracksAudioPlay']) for each in album_list_data['data']['tracksAudioPlay']: try: detail_url = 'http://www.ximalaya.com/tracks/%s.json' % each['trackId'] response = requests.get(detail_url, headers=self.header) item = json.loads(response.content) episode = self.podcast.add_episode() episode.id = str(each['index']) episode.title = each['trackName'] print(self.podcast.name + '=====' + each['trackName']) image = each['trackCoverPath'].split('!')[0] if (image[-4:] == '.gif' or image[-4:] == '.bmp'): episode.image = self.podcast.image else: episode.image = image if item['intro']: episode.summary = item['intro'].replace('\r\n', '') else: episode.summary = each['trackName'] episode.link = 'http://www.ximalaya.com%s' % each['albumUrl'] episode.authors = [Person("forecho", '*****@*****.**')] episode.publication_date = self.reduction_time(item['time_until_now'], item['formatted_created_at']) episode.media = Media(each['src'], each['duration']) episode.position = count - each['index'] + 1 except Exception as e: print('异常:', e) print('异常 URL:', 'http://www.ximalaya.com%s' % each['trackUrl']) traceback.print_exc() # 生成文件 # print self.podcast.rss_str() self.podcast.rss_file('ximalaya/%s.rss' % self.album_id, minimize=True)
def test_categoryWithSubcategory(self): c = Category("Arts", "Food") self.fg.category = c channel = self.fg._create_rss().find("channel") itunes_category = channel.find("{%s}category" % self.nsItunes) assert itunes_category is not None itunes_subcategory = itunes_category\ .find("{%s}category" % self.nsItunes) assert itunes_subcategory is not None self.assertEqual(itunes_subcategory.get("text"), c.subcategory)
def test_oldCategoryIsAcceptedWithWarning(self): # Replacement of assertWarns in Python 2.7 with warnings.catch_warnings(record=True) as w: # Replacement of assertWarns in Python 2.7 warnings.simplefilter("always", LegacyCategoryWarning) c = Category("Government & Organizations") self.assertEqual(c.category, "Government & Organizations") # Replacement of assertWarns in Python 2.7 self.assertEqual(len(w), 1) self.assertIsInstance(w[0].message, LegacyCategoryWarning)
def rssfeed(request, programid): """ Builds the rss feed for a program identified by it's id. (int) 1. Fetches all episodes of the program from the digas db. 2. gets the programinfo from the app db 3. Uses podgen to do the actual XML-generation. """ podcasts = DigasPodcast.objects.using('digas').filter( softdel=0, program=int(programid)).only('program', 'title', 'remark', 'author', 'createdate', 'broadcastdate', 'filename', 'filesize', 'duration', 'softdel').order_by('-createdate') programinfo = ProgramInfo.objects.get(programid=int(programid)) # loading globalsettings here, and not at the module_level # This way django won't explode because of missing # constance_config table when we start on scratch # or set up in a new environment. from .models import globalsettings p = Podcast( name=programinfo.name, subtitle=programinfo.subtitle, description=programinfo.description, website=feed_url(programid), # programinfo.website, explicit=programinfo.explicit, category=Category(programinfo.category), authors=[globalsettings.owner], language=programinfo.language, owner=globalsettings.owner, feed_url=feed_url(programid), new_feed_url=feed_url(programid), image=programinfo.image_url, ) for episode in podcasts: # Get pubdate from createdate or broadcastdate pubdate = digas2pubdate(episode.createdate, episode.broadcastdate) # Add the episode to the list p.episodes.append( Episode( title=episode.title, media=Media(mp3url(episode.filename), episode.filesize), link=mp3url(episode.filename), # multifeedreader uses this. id=guid(episode.filename), summary=episode.remark, publication_date=pubdate)) # send it as unicode rss = u'%s' % p return HttpResponse(rss, content_type='application/xml')
def test_oldSubcategoryIsAcceptedWithWarnings(self): # Replacement of assertWarns in Python 2.7 with warnings.catch_warnings(record=True) as w: # Replacement of assertWarns in Python 2.7 warnings.simplefilter("always", LegacyCategoryWarning) c = Category("Technology", "Podcasting") self.assertEqual(c.category, "Technology") self.assertEqual(c.subcategory, "Podcasting") # Replacement of assertWarns in Python 2.7 self.assertEqual(len(w), 1) self.assertIsInstance(w[0].message, LegacyCategoryWarning)
def test_constructorWithSubcategory(self): # Replacement of assertWarns in Python 2.7 with warnings.catch_warnings(record=True) as w: # Replacement of assertWarns in Python 2.7 warnings.simplefilter("always", LegacyCategoryWarning) c = Category("Arts", "Food") self.assertEqual(c.category, "Arts") self.assertEqual(c.subcategory, "Food") # No warning should be given # Replacement of assertWarns in Python 2.7 self.assertEqual(len(w), 0)
def create_podcast(name, desc, website): p = Podcast() #if not res: p.name = name p.description = desc p.authors = [Person("Dawn News", "*****@*****.**")] p.website = website p.image = "http://3.15.38.214/zarahatkay/cover_art.png" p.language = "en-US" p.feed_url = "http://3.15.38.214/zarahatkay" p.category = Category("News & Politics") p.explicit = False return p
def populate(self, show) -> None: metadata = self.data[self._get_key(show)] for attribute, value in metadata.items(): if hasattr(show, attribute): if attribute in ("publication_date", "last_updated"): try: setattr(show, attribute, strptime(value, "%Y-%m-%d %H:%M:%S %z")) except ValueError: logger.warning( "Date %(date)s in file %(file)s could not be parsed, so it was ignored.\n" "Make sure it's on the following form (±HHMM being timezone offset):\n" " YYYY-MM-DD HH:MM:SS ±HHMM", { "date": metadata['date'], "file": self._config_file }) elif attribute == "authors": authors = [ Person(p.get('name'), p.get('email')) for p in value ] show.authors = authors elif attribute == "web_master": show.web_master = Person(value.get('name'), value.get('email')) elif attribute == "category": if len(value) == 2: show.category = Category(value[0], value[1]) else: show.category = Category(value[0]) else: setattr(show, attribute, value) else: logger.warning( "Attribute %(keys)s for %(id)s was not recognized.", { "id": show.id, "keys": attribute })
def main(event, context): dynamodb = boto3.resource('dynamodb', region_name='sa-east-1') table = dynamodb.Table('semservidor-dev') podcasts = table.scan() author = Person("Evandro Pires da Silva", "*****@*****.**") p = Podcast( name="Sem Servidor", description= "Podcast dedicado a arquitetura serverless, com conteúdo de qualidade em português.", website="https://semservidor.com.br", explicit=False, copyright="2020 Evandro Pires da Silva", language="pr-BR", authors=[author], feed_url= "https://3tz8r90j0d.execute-api.sa-east-1.amazonaws.com/dev/podcasts/rss", category=Category("Music", "Music History"), owner=author, image="http://d30gvsirhz3ono.cloudfront.net/logo_semservidor_teste.jpg", web_master=Person(None, "*****@*****.**")) items = podcasts['Items'] for item in items: base_url = "http://d30gvsirhz3ono.cloudfront.net/" file_path = base_url + item['info']['arquivo']['nome'] p.episodes += [ Episode(title=item['info']['episodio'], media=Media(file_path, int(item['info']['arquivo']['tamanho'])), summary=item['info']['descricao'], position=int(item['id'])) ] p.apply_episode_order() rss = p.rss_str() response = { "statusCode": 200, "headers": { "content-type": "application/xml" }, "body": rss } return response
def generate_rss_from_articles(feed_settings, articles): """ Creates a FeedGenerator feed from a set of feed_entries. :param feed_settings: a feed_settings object containing :param articles: :return: """ # Initialize the feed podcast = Podcast() podcast.name = feed_settings.title author = Person(feed_settings.author['name'], feed_settings.author['email']) podcast.authors.append(author) podcast.website = feed_settings.source_page_url podcast.copyright = feed_settings.copyright podcast.description = feed_settings.subtitle podcast.summary = feed_settings.subtitle podcast.subtitle = feed_settings.subtitle podcast.language = 'vi' podcast.feed_url = feed_settings.output_url podcast.image = feed_settings.img_url podcast.category = Category('Music', 'Music Commentary') podcast.explicit = False # p.complete = False # p.new_feed_url = 'http://example.com/new-feed.rss' podcast.owner = author # p.xslt = "http://example.com/stylesheet.xsl" vt_tz = pytz.timezone('Asia/Ho_Chi_Minh') pastdate = datetime.datetime(2000, 1, 1, 0, 0).astimezone(vt_tz) # podcast.last_updated = datetime.datetime.now(vt_tz) for article in articles: episode = podcast.add_episode() episode.id = article.link episode.title = article.title episode.summary = article.description episode.link = article.link # episode.authors = [Person('Lars Kiesow', '*****@*****.**')] episode.publication_date = article.pub_date pastdate = max(pastdate, article.pub_date) # episode.media = Media.create_from_server_response(article.media, size=None, duration=None) episode.media = Media(article.media, size=None, duration=None, type=article.type) podcast.last_updated = pastdate podcast.publication_date = pastdate return podcast
def test_escapedIsAccepted(self): c = Category("Sports & Recreation", "College & High School") self.assertEqual(c.category, "Sports & Recreation") self.assertEqual(c.subcategory, "College & High School")
def create_rss(type, download): """Create an example podcast and print it or save it to a file.""" # Create the Podcast & initialize the feed default_channel = Channel.defaultChannel() p = Podcast() p.name = default_channel.name p.description = default_channel.description p.website = default_channel.website p.explicit = default_channel.explicit p.image = default_channel.image p.copyright = default_channel.copyright p.language = default_channel.language p.feed_url = default_channel.feed_url p.category = Category(default_channel.category) # p.category = Category('Technology', 'Podcasting') # p.xslt = "https://example.com/feed/stylesheet.xsl" # URL of XSLT stylesheet p.authors = [Person(default_channel.authors, default_channel.authors_email)] p.owner = Person(default_channel.owner, default_channel.owner_email) # Other Attributes p.generator = " " # Others for iTunes # p.complete = False # p.new_feed_url = 'http://example.com/new-feed.rss' # e1 = p.add_episode() # e1.id = 'http://lernfunk.de/_MEDIAID_123#1' # e1.title = 'First Element' # e1.summary = htmlencode('''Lorem ipsum dolor sit amet, consectetur adipiscing elit. Tamen # aberramus a proposito, et, ne longius, prorsus, inquam, Piso, si ista # mala sunt, placet. Aut etiam, ut vestitum, sic sententiam habeas aliam # domesticam, aliam forensem, ut in fronte ostentatio sit, intus veritas # occultetur? Cum id fugiunt, re eadem defendunt, quae Peripatetici, # verba <3.''') # e1.link = 'http://example.com' # e1.authors = [Person('Lars Kiesow', '*****@*****.**')] # e1.publication_date = datetime.datetime(2014, 5, 17, 13, 37, 10, tzinfo=pytz.utc) # # e1.media = Media("http://example.com/episodes/loremipsum.mp3", 454599964, # # duration= # # datetime.timedelta(hours=1, minutes=32, seconds=19)) # e1.media = Media("http://example.com/episodes/loremipsum.mp3", 454599964) # Add some episodes p.episodes += [ Episode(title = download.title, subtitle = download.subtitle, # id=str(uuid.uuid4()), position =2, media = Media(download.media_url, size=download.media_size, duration=timedelta(seconds=download.media_duration)), image = download.image_url, publication_date = datetime(year=2021, month=1, day=8, hour=10, minute=0, tzinfo=pytz.utc), summary = download.summary) , Episode(title="Episode 2 - The Crazy Ones", subtitle="this is a cool episode, this is for th crazy ones", position=1, image="https://github.com/oliverbarreto/PersonalPodcast/raw/main/site-logo-1400x1400.png", media=Media("https://github.com/oliverbarreto/PersonalPodcast/raw/main/downloaded_with_pytube_Apple%20Steve%20Jobs%20Heres%20To%20The%20Crazy%20Ones.mp4", type="audio/mpeg", size=989, duration=timedelta(hours=0, minutes=1, seconds=1)), publication_date = datetime(year=2021, month=1, day=6, hour=10, minute=0, tzinfo=pytz.utc), summary=htmlencode("wow wow wow summary")) , Episode(title="Episode 3 - The Super Crazy", subtitle="crazy ones revisited", position=0, image="https://github.com/oliverbarreto/PersonalPodcast/raw/main/site-logo-1400x1400.png", media=Media("https://drive.google.com/file/d/1X5Mwa8V0Su1IDqhcQL7LdzEY0VaMC1Nn", type="audio/mpeg", size=989, duration=timedelta(hours=0, minutes=1, seconds=1)), publication_date = datetime(year=2021, month=1, day=10, hour=10, minute=0, tzinfo=pytz.utc), summary=download.summary) ] # Should we just print out, or write to file? if type == 'print': # Print print_enc(p.rss_str()) elif type== 'feed.xml': # Write to file p.rss_file(type, minimize=False) print("\n") print("feed.xml created !!!")
def test_constructorCaseInsensitive(self): c = Category("arTS", "FOOD") self.assertEqual(c.category, "Arts") self.assertEqual(c.subcategory, "Food")
def test_constructorWithoutSubcategory(self): c = Category("Arts") self.assertEqual(c.category, "Arts") self.assertTrue(c.subcategory is None)
def test_constructorWithSubcategory(self): c = Category("Arts", "Food") self.assertEqual(c.category, "Arts") self.assertEqual(c.subcategory, "Food")
'filename': file_local_path, 'name': video.title }) except HTTPError as err: print('Can not parse this video bacause of HTTPError.') # Create Podcast object and fill it with episodes podcast_object = Podcast( name=CONFIG['podcast_name'], description=CONFIG['podcast_description'], website=CONFIG['podcast_website'], explicit=False, image=CONFIG['podcast_image'], language=CONFIG['podcast_language'], authors=[Person(CONFIG['podcast_author'], CONFIG['podcast_author_email'])], owner=Person(CONFIG['podcast_owner'], CONFIG['podcast_owner_email']), category=Category(CONFIG['podcast_category'], CONFIG['podcast_subcategory'])) for item in db: web_media_path = "%s/podcast_%s.mp4" % (CONFIG['podcast_media_server'], item['link'][9:]) podcast_object.add_episode( Episode(title=item['name'], media=Media(web_media_path, os.stat(item['filename']).st_size, type="audio/mpeg"))) # Generating RSS podcast_object.rss_file(('%s/rss.xml' % CONFIG['data_path']), minimize=True)
def generate(name, description, website, explicit, image, author_name, author_email, feed_path, copyright, language, category, blog, blog_path, verbose, folder): """Generate a podcast from mp3 files located in the provided FOLDER""" if verbose: logging.basicConfig(level=logging.DEBUG) else: logging.basicConfig(level=logging.INFO) attrs = locals() logging.debug('Processing input: %s' % (attrs)) del attrs['folder'] del attrs['author_name'] del attrs['author_email'] del attrs['verbose'] del attrs['feed_path'] del attrs['blog'] del attrs['blog_path'] attrs['authors'] = [Person(author_name, author_email)] attrs['owner'] = attrs['authors'][0] attrs['category'] = Category(category) feed_name = name.lower().replace(' ', '_') + '.rss' feed_base = '%s/%s' % (website, feed_path) feed_url = '%s/%s' % (feed_base, feed_name) attrs['feed_url'] = feed_url logging.info('Creating podcast %s, feed %s' % (name, feed_url)) p = Podcast(**attrs) for fpath in sorted(glob.glob('%s*.mp3' % (folder))): logging.info('Adding episode %s' % (fpath)) fname = os.path.basename(fpath) size = os.path.getsize(fpath) logging.debug('Filename: %s, size %i' % (fname, size)) try: tag = ID3(fpath) except ID3NoHeaderError: logging.error('%s is not a valid mp3 file, ignoring it' % (fpath)) continue logging.debug('Read tag: %s' % (tag)) e = Episode() if 'TPE1' in tag: e.authors = [Person(tag['TPE1'][0])] else: e.authors = attrs['authors'] e.title = tag['TIT2'][0] e.subtitle = e.title if 'COMM::eng' in tag: e.summary = tag['COMM::eng'][0] else: e.summary = description episode_url = '%s/%s' % (feed_base, fname) logging.debug('Episode url: %s' % (episode_url)) e.media = Media(episode_url, size, type='audio/mpeg') e.media.populate_duration_from(fpath) pubdate = datetime.strptime(tag['TDRC'][0].text[:10], '%Y-%m-%d') pubdate = pubdate.replace(tzinfo=pytz.utc) e.publication_date = pubdate if blog: blog_post = '' short_name = re.search('[a-z]*_-_([a-z_]*[#0-9]*)', fname) if short_name: blog_post = short_name.group(1).replace('_', '-').\ replace('#', '') + '.html' e.link = '%s/%s/%s' % (website, blog_path, blog_post) p.episodes.append(e) feed_local_path = '%s%s' % (folder, feed_name) logging.info('Generating feed in %s' % (feed_local_path)) p.rss_file(feed_local_path, minimize=False)
def test_escapedIsAccepted(self): c = Category("Kids & Family", "Pets & Animals") self.assertEqual(c.category, "Kids & Family") self.assertEqual(c.subcategory, "Pets & Animals")
# write the new sessions json file updated_session_items = new_items + session_items for item in updated_session_items: item['link'] = f'{ipfs_prefix}{item["CID"]}{ipfs_suffix}' with open(sessions_filename, 'w') as outfile: json.dump(updated_session_items, outfile, indent=2) print('>>> wrote fresh sessions.json file') # write the new rss file p = Podcast() p.name = "The Objectivism Seminar" p.category = Category("Society & Culture", "Philosophy") p.language = "en-US" p.explicit = True p.description = ( "A weekly online conference call to systematically study " + "the philosophy of Objectivism via the works of prominent Rand scholars.") p.website = "https://www.ObjectivismSeminar.com" p.image = "https://www.ObjectivismSeminar.com/assets/images/atlas-square.jpg" p.feed_url = "https://www.ObjectivismSeminar.com/archives/rss" p.authors = [Person("Greg Perkins, Host", "*****@*****.**")] p.owner = Person("Greg Perkins", "*****@*****.**") p.episodes += [ Episode(title=x['title'], media=Media(x['link'], type="audio/mpeg", size=x['length']), id=x['GUID'],
def album(self): album_info = requests.get(self.album_info_url.format(self.album_id), headers=self.header).content album_info_content = json.loads(album_info.decode('utf-8')) if album_info_content['ret'] == 200: album_info_data = album_info_content['data'] # 初始化 self.podcast = Podcast() self.podcast.name = album_info_data['mainInfo']['albumTitle'] self.podcast.authors.append( Person("Powered by forecho", '*****@*****.**')) self.podcast.website = self.album_url.format(self.album_id) self.podcast.copyright = 'cc-by' if album_info_data['mainInfo']['richIntro']: self.podcast.description = album_info_data['mainInfo'][ 'richIntro'] else: self.podcast.description = self.podcast.name self.podcast.language = 'cn' self.podcast.image = 'https:' + album_info_data['mainInfo'][ 'cover'].split('!')[0] self.podcast.feed_url = 'http://podcast.forecho.com/ximalaya/%s.rss' % self.album_id self.podcast.category = Category('Technology', 'Podcasting') self.podcast.explicit = False self.podcast.complete = False self.podcast.owner = Person("forecho", '*****@*****.**') page_num = 1 # py2 +1 track_total_count = math.ceil( album_info_data['tracksInfo']['trackTotalCount'] / self.page_size) + 1 while page_num <= track_total_count: album_list = requests.get(self.album_list_url.format( self.album_id, page_num, self.page_size), headers=self.header).content album_list_content = json.loads(album_list.decode('utf-8')) count = len(album_list_content['data']['tracksAudioPlay']) for each in album_list_content['data']['tracksAudioPlay']: try: detail = requests.get(self.detail_url.format( each['trackId']), headers=self.header).content detail_content = json.loads(detail.decode('utf-8')) episode = self.podcast.add_episode() episode.id = str(each['index']) episode.title = each['trackName'] print(self.podcast.name + '=====' + each['trackName']) image = each['trackCoverPath'].split('!')[0] if image[-4:] == '.png' or image[-4:] == '.jpg': episode.image = 'https:' + image else: episode.image = self.podcast.image if 'intro' in detail_content: episode.summary = detail_content['intro'].replace( '\r\n', '') else: episode.summary = each['trackName'] episode.link = 'http://www.ximalaya.com%s' % each[ 'albumUrl'] episode.authors = [ Person("forecho", '*****@*****.**') ] episode.publication_date = self.reduction_time( detail_content['createdAt']) episode.media = Media(each['src'], each['duration']) episode.position = count - each['index'] + 1 except Exception as e: print('异常:', e) print('异常 URL:', 'https://www.ximalaya.com%s' % each['trackUrl']) traceback.print_exc() # 生成文件 # print self.podcast.rss_str() page_num = page_num + 1 self.podcast.rss_file('ximalaya/%s.rss' % self.album_id, minimize=True)
def lambda_handler(event, context): print('Starting cccRssBuilder Lambda function') # Get episodes from DynamoDB episodes = query_episodes() episodes.sort(key=lambda x: x['episode-num']) # Create the podcast feed # Main podcast info comes from "episode 0" episodeInfo = episodes[0] separator = ', ' p = Podcast() p.name = episodeInfo['name'] p.description = episodeInfo['description'] p.website = episodeInfo['website'] p.explicit = episodeInfo['explicit'] p.image = episodeInfo['image'] p.feed_url = episodeInfo['feed-url'] p.language = episodeInfo['language'] p.category = Category(episodeInfo['category'], episodeInfo['subcategory']) p.owner = Person(episodeInfo['owner-name'], episodeInfo['owner-email']) p.authors = [Person(episodeInfo['owner-name'], episodeInfo['owner-email'])] # Process each episode for episode in episodes: # Skip "Episode 0" if episode['episode-num'] == 0: continue # Check if episode contains media file info (name, duration, size). If not, add it to db and episode object. if 'media-file' not in episode: episodeNum = episode['episode-num'] print('Analyzing media file for episode', episodeNum) mediaFile = 'ccc-{:03d}-{}.mp3'.format(int(episodeNum), episode['pub-date']) print('Media file:', mediaFile) localMediaFile = '/tmp/' + mediaFile s3 = boto3.client('s3') s3.download_file('kwksolutions.com', 'ccc/media/' + mediaFile, localMediaFile) # Try to analyze the mp3 file - looking for duration and file size try: audio = MP3(localMediaFile) except: print('Not an MP3 file!') return duration = round(audio.info.length) hours = int(duration / 3600) minutes = int((duration % 3600) / 60) seconds = duration % 60 if hours == 0: durationStr = '{:02d}:{:02d}'.format(minutes, seconds) else: durationStr = '{:02d}:{:02d}:{:02d}'.format( hours, minutes, seconds) size = str(os.path.getsize(localMediaFile)) update_episode(episodeNum, mediaFile, size, durationStr) episode['media-file'] = mediaFile episode['size'] = size episode['duration'] = durationStr # Figure out all the info needed for the episode object mediaURL = 'https://www.kwksolutions.com/ccc/media/' + episode[ 'media-file'] durationList = episode['duration'].split(':') secs = int(durationList[-1]) mins = int(durationList[-2]) try: h = int(durationList[-3]) except: h = 0 pubdateList = episode['pub-date'].split('-') year = int(pubdateList[0]) month = int(pubdateList[1]) day = int(pubdateList[2]) # Build the episode object e = p.add_episode() e.id = mediaURL e.title = 'Episode ' + str(episode['episode-num']) e.summary = episode['description'] e.link = 'http://christcommunitycarmel.org/get-involved/podcasts' e.publication_date = datetime.datetime(year, month, day, 12, 00, 00, tzinfo=pytz.timezone('EST')) e.media = Media(mediaURL, episode['size'], duration=datetime.timedelta(hours=h, minutes=mins, seconds=secs)) # Write the rss file print('Writing RSS file to S3') rssLocalFile = '/tmp/podcast.rss' rssS3File = 'ccc/podcast.rss' p.rss_file(rssLocalFile) s3 = boto3.client('s3') s3.upload_file(rssLocalFile, 'kwksolutions.com', rssS3File, ExtraArgs={'ContentType': 'text/xml'}) return