### cosmos-wormhole

小宇宙 API (Python Version)

🐙 GitHub: cosmos-wormhole | 🐍 PyPI: cosmos-wormhole

### 安装¶

    pip install cosmos-wormhole

### 用例¶

    from cosmos_wormhole import Client

    c = Client()
    await c.login()

    打开小宇宙App，使用「发现」Tab - 搜索框右侧「扫一扫」登录
    PS: 小宇宙会提示登录「小宇宙主播后台」。主播后台和主App账号互通

        █▀▀▀▀▀█ ▄▄▄ █▄▀▀▀▄ ▀██  █   █ █▀▀▀▀▀█
        █ ███ █ █ ▄█ █▄▄ ▄   █▀▄█▄▀█  █ ███ █
        █ ▀▀▀ █  ▄▄█▄▄▄ ▄█ ▀ █▄▀▄▄▀ █ █ ▀▀▀ █
        ▀▀▀▀▀▀▀ █ █ █▄█▄█▄█ ▀ ▀▄▀ ▀▄█ ▀▀▀▀▀▀▀
        ▀ ▄▄▄▄▀▄██ █ ▀  █ ▄▀ █▄█▄▀ ▄██▀ ▄███
          ▀▄ ▄▀ ▄▄▀ █▀ ▀▀ ▀█▄ █ ▄ ██▀ ▄▀▀▀▀▀█
        ▀ █▄▀ ▀▄▀▄ ▀ ▀▀██  ▄█▄ ▄█ ▄███▀█ ▄ ▄▀
        ▀▄██▄ ▀██ █▀ ▀ █▀ ▀  ▄█   ▀▀█▀▀█▀█▄▄█
        ▄▄ █▀ ▀ █▀▄▄ ▄█ ▄ ▀ ▀█▀█▄█▄█▄▀▀▄▀ ██
        ▀▀▀▄▄ ▀██▀▄██▀ ▄█ █▀ ▀▄▀▀ ▀▀▄▄█▀█▀▀ █
           █ ▄▀▄█▀▀█ █▄ ▀█▄▄▀ ▄▄▀▀██  ▀ █ █▄
        ▄▀▀▀█ ▀ ▄ █▄▀██▀██▄ █▀▄▄▀  ▀▀▄████  █
        █▀   ▀▀█ ▀█   ▀▀ ▀▄▀████▀▄█▄██▀  ▄  ▀
        █ ▄▄▀▀▀▄███  ▄ ▀█▀▀█  ▀▄█ ▄▀ ▀  █▄█▀█
        ▀ ▀▀ ▀▀▀▄▀▄█ █▀█▄▀▄██▄▀▄▀▀▀▀█▀▀▀█▀▀▀▀
        █▀▀▀▀▀█  ▀▄█   ▀█▀▀▀ ▄ ▀ ▀▀▄█ ▀ █  ▄█
        █ ███ █  ▄▀ ███▀ ▄▀ ███▄▀█ ▀███▀▀▄█ ▄
        █ ▀▀▀ █   ▀▀▄▀ ▄▄▀  ▀ █ █▀█▀█▀  ▄▀▀▀█
        ▀▀▀▀▀▀▀ ▀▀   ▀▀ ▀  ▀▀       ▀ ▀▀    ▀

    二维码已被扫描，请在小宇宙App中确认登录。
    登录成功！

⚠️ PS:

登录成功后，token会保存在 `~/.local/state/cosmos-wormhole/token.json`文件中。如无必要，不要改动该文件。

#### 1. 订阅¶

    async for podcast in c.subscription.list():
        print(f"🎙️{podcast}")
        if podcast.title == "史蒂夫说":
            async for episode in c.episode.list_by_podcast(podcast.id):
                print(f"🎧{episode}")
                async for comment in c.comment.list_by_episode(episode.id, "HOT"):
                    print(f"💬{comment}")
                    async for reply in c.reply.list_by_comment(comment.id, "SMART"):
                        print(f"↩️{reply}")
                    break
                break
            break

    🎙️Podcast(pid=6278b07ad6e7a5551f799dd0, title=公司茶水间)
    🎙️Podcast(pid=65a625966d045a7f5e0b5640, title=不止金钱)
    🎙️Podcast(pid=625e7ba592a9f7a721b86d20, title=蜜獾吃书)
    🎙️Podcast(pid=5f4475a89504bbdb77b50bd0, title=最近买了什么书)
    🎙️Podcast(pid=5e2aaf88418a84a046546819, title=梁文道·八分)
    🎙️Podcast(pid=5e3bdf08418a84a046fb556c, title=大内密谈)
    🎙️Podcast(pid=64379296ff8a107611a67208, title=史蒂夫说)
    🎧Episode(eid=6874e0a193fd2d72b820959f, pid=64379296ff8a107611a67208, title=史蒂夫说432期 - 回信：不了解自己的人容易执着于肤浅的成败)
    💬Comment(id=687519a1e26a3567d425b549, text=挺认同steve给第一位时常抑郁和虚无的咨询者给的建议，脑子想根本不行的，还是需要从身体开始拯救自己，我也是时常这样，如果去练舞跳舞，就会好点)
    ↩️Comment(id=6875af7944c4a5b6c470cf5e, text=11:47 是的，身体的正反馈对心理的康复有利。我游泳教练说很多老年人睡不着就来游泳，游完睡眠嘎嘎好😂。以及，有社交体验的运动会对心理恢复更好，即使每次只有很浅薄的small talk. 以及有些朴素的建议，抑郁了可以去干点体力活或做一些体力工作。从功利的角度来说，因为没时间想七想八，既可以消耗体力睡好觉，又可以拿钱。)
    ↩️Comment(id=68751e852134314d913b5e61, text=ip正确，舞起来吧哈哈哈哈)
    ↩️Comment(id=68770e5111d4f41403602567, text=同意..当很迷茫的时候，身体上的探索进步多多少少给了我一点正反馈让我不那么讨厌躺平的自己⋯，就算一点点。都至少给了我，人生还有能靠自己控制，生活是没那么坏的感受。)
    ↩️Comment(id=6878d33d15d8379d4db3b764, text=是的，我也决定今年必须去游泳了！)
    ↩️Comment(id=68763c58e8e669b5695d782e, text=很认同这个点，身体上的疲惫是最好的安眠药)

#### 2. 节目/单集¶

    podcast = await c.podcast.get('5e280faa418a84a0461f9ad8')
    print(podcast)
    episode = await c.episode.get('68776e08f01740ccc77a596b')
    print(episode)

    Podcast(pid=5e280faa418a84a0461f9ad8, title=日谈公园)
    Episode(eid=68776e08f01740ccc77a596b, pid=5e280faa418a84a0461f9ad8, title=vol.719 请马伯庸亲自说说《长安的荔枝》的创作秘辛)

#### 3. 节目更新¶

    cnt = 0
    async for episode in c.inbox.list():
        print(episode)
        cnt += 1
        if cnt >= 5:
            break

    Episode(eid=687ec6ff96cb2d71096ef22c, pid=5e4515bd418a84a046e2b11a, title=Vol.292 现代性与大屠杀：普通人与恶的距离有多远？)
    Episode(eid=687debb9a12f9ff06a3bcae5, pid=5e284c39418a84a046263d8a, title=vol.470 零基础Live Aid入门（上）)
    Episode(eid=687e6bd796cb2d710960fd68, pid=61933ace1b4320461e91fd55, title=127: 与真格戴雨森 25 AI 中场复盘：OpenAI的IMO金牌、Kimi K2翻盘、Agent普及和抢人大战)
    Episode(eid=687e538ca9dec9250073653d, pid=5e280faa418a84a0461f9ad8, title=vol.720 金世佳：我对不成功的人生充满感激（上）)
    Episode(eid=687dca72a9dec9250057d909, pid=5e2839ca418a84a0462431b7, title=圆桌会谈：炎炎夏日，我在泳池浴室寻找恶臭之源！)

#### 4. 播放列表¶

    cnt = 0
    async for playlist in c.playlist.list():
        print(playlist)
        cnt += 1
        if cnt >= 5:
            break

    687ce8e4a9dec925003c8efd
    68787863a12f9ff06a9448f8
    683e851c38dcc57c644718eb
    6879df2da9dec92500e81fdf
    68776e08f01740ccc77a596b

#### 5. 用户¶

    my_profile = await c.profile.get()
    print(my_profile)
    podcaster = await c.profile.get('5e82d3531bfbbc3dad854379') # 《文化有限》主播 杨大壹
    print(podcaster)

    User(uid=5e2987043419f408b3f7f23f, nickname=以太)
    User(uid=5e82d3531bfbbc3dad854379, nickname=杨大壹)

#### 6. 关注¶

    cnt = 0
    async for user in c.followee.list_following(my_profile.id):
        print(user)
        cnt += 1
        if cnt >= 5:
            break

    User(uid=6045751fe0f5e723bb4aafbf, nickname=袁梦_Nina)
    User(uid=62f3b03eedce67104a074bf6, nickname=蒋寻)
    User(uid=60b861e2e0f5e723bbb4d9f6, nickname=妙雅的兔子)
    User(uid=5e808f0e1bfbbc3dad8419c9, nickname=免子队长油百万)
    User(uid=5e739699b3c5bca5f63af74b, nickname=Alissi)

#### 7. 粉丝¶

    cnt = 0
    async for user in c.follower.list_follower(my_profile.id):
        print(user)
        cnt += 1
        if cnt >= 5:
            break

    User(uid=62bdba2cedce67104aeef82e, nickname=磊一鸣)
    User(uid=64890337edce67104aafed32, nickname=言云星月area)
    User(uid=63c781efedce67104a897dfc, nickname=泡泡po33)
    User(uid=5eab8af59c735f9cf4eb3adb, nickname=废材少女幽香酱)
    User(uid=5fe13e59e0f5e723bb847302, nickname=歪歪爱学习)

#### 8. 收听历史¶

    cnt = 0
    async for episode in c.history.list():
        print(episode)
        cnt += 1
        if cnt >= 5:
            break

    Episode(eid=687ce8e4a9dec925003c8efd, pid=60de7c003dd577b40d5a40f3, title=布拉德·皮特银幕上演 F1 传奇，现实世界为何却少有美国车手？)
    Episode(eid=68787863a12f9ff06a9448f8, pid=65716792d6e0ff5822d25668, title=E26 你离用好定投这个武器，只差这一期内容！| 实操篇)
    Episode(eid=683e851c38dcc57c644718eb, pid=62382c1103bea1ebfffa1c00, title=No.153 📠 「史前」科技巨头四通与中关村教父 | 中国互联网故事1)
    Episode(eid=6879df2da9dec92500e81fdf, pid=5f912d9783c34e85ddd7e23d, title=179.身体已不是从前那个少年，however心还是。)
    Episode(eid=68776e08f01740ccc77a596b, pid=5e280faa418a84a0461f9ad8, title=vol.719 请马伯庸亲自说说《长安的荔枝》的创作秘辛)

#### 9. 收藏的单集¶

    cnt = 0
    async for episode in c.favorited_episode.list():
        print(episode)
        cnt += 1
        if cnt >= 5:
            break

    Episode(eid=6626ece8db5f58a80d0d31db, pid=5e4515bd418a84a046e2b11a, title=Vol.227 世界读书日，跟143位主播共享一份书单)
    Episode(eid=66291d2cff598d65f202b6a1, pid=5e280faa418a84a0461f9ad8, title=vol.615 和纵横四海携隐Melody聊聊如何摆脱“时间贫困”)
    Episode(eid=6452e781b7b3c21b65ce4669, pid=6022a180ef5fdaddc30bb101, title=Vol.109 当今最重要的基础设施，在海底)
    Episode(eid=68776e08f01740ccc77a596b, pid=5e280faa418a84a0461f9ad8, title=vol.719 请马伯庸亲自说说《长安的荔枝》的创作秘辛)
    Episode(eid=6426bfd13f40bdefe7f4aaf7, pid=5e280fad418a84a0461fb38b, title=E714.「废物」作家自述：想过正常的有尊严的生活，怎么这么难)

#### 10. 收藏的评论¶

    cnt = 0
    async for comment in c.favorited_comment.list():
        print(comment)
        cnt += 1
        if cnt >= 5:
            break

    Comment(id=635724ff0236bb00100d5aca, text=【萌二评论📑文化有限の合集，请接收！】
    🌠频道仪式
    🔗 https://www.xiaoyuzhoufm.com/episode/5e4515bd418a84a046e2b128
    🔗 https://www.xiaoyuzhoufm.com/episode/6164c36ebcb2fee71fae4c24
    🔗 https://www.xiaoyuzhoufm.com/episode/633b6a39a5d434d0ee91ba9f
    🔗 https://www.xiaoyuzhoufm.com/episode/62e85c62472e726a52ecd888
    🌠综合特缉
    🌸春日篇：
    🔗 https://www.xiaoyuzhoufm.com/episode/603d758f30638eea2cef9e2f
    🏖夏日篇：
    🔗 https://www.xiaoyuzhoufm.com/episode/62b0fcb8ba5434fc2d660540
    🍁秋日篇：
    🔗 https://www.xiaoyuzhoufm.com/episode/6328f4b63210b0e9e7708a52
    🍾节日篇：春节+圣诞+万圣+感恩
    🔗 https://www.xiaoyuzhoufm.com/episode/61f86b2680651919bbdee145
    🔗 https://www.xiaoyuzhoufm.com/episode/61ba74e7a7eccbe3918adf69
    🔗 https://www.xiaoyuzhoufm.com/episode/6177395577a31cddee7b74ea
    🔗 https://www.xiaoyuzhoufm.com/episode/5fbc4f9ddee9c1e16db222ba
    🌠朗诵配乐
    🔗 https://www.xiaoyuzhoufm.com/episode/60da58b403c9bf1da959dd08
    🔗 https://www.xiaoyuzhoufm.com/episode/62f196e803da6b049bdbeef7
    🔗 https://www.xiaoyuzhoufm.com/episode/61e5f62aeffcbded188a717f
    🌠读书写作
    🔗 https://www.xiaoyuzhoufm.com/episode/5f56ce8283c34e85dd275e4f
    🔗 https://www.xiaoyuzhoufm.com/episode/5ec3bd68418a84a046a8fc24
    🌠精准沟通
    🔗 https://www.xiaoyuzhoufm.com/episode/63322f7e120ae67f87490f03
    🔗 https://www.xiaoyuzhoufm.com/episode/61b7d22c248ff750af64e1ee
    🌠家庭亲子
    🔗 https://www.xiaoyuzhoufm.com/episode/62c371b595b30b04003c661f
    🔗 https://www.xiaoyuzhoufm.com/episode/5e4515bd418a84a046e2b133
    🔗 https://www.xiaoyuzhoufm.com/episode/6062612b3bdce47be7e06c36
    🔗 https://www.xiaoyuzhoufm.com/episode/63040af7e72c1f7ae44e7258
    🌠心理健康
    🔗 https://www.xiaoyuzhoufm.com/episode/611aeeef629a774bd842ec2d
    🔗 https://www.xiaoyuzhoufm.com/episode/62141a78c8cea1e1315e52a0
    🔗 https://www.xiaoyuzhoufm.com/episode/630d450dc69aabcde0f1b0d6)

#### 11. 搜索节目¶

    cnt = 0
    async for podcast in c.podcast_search.search("脱口秀"):
        print(podcast)
        cnt += 1
        if cnt >= 5:
            break

    Podcast(pid=5e280fa7418a84a0461f912b, title=谐星聊天会)
    Podcast(pid=660840711519139e4f9699ef, title=小fool人)
    Podcast(pid=65bb55f6513a776b57dedb32, title=李诞)
    Podcast(pid=60e43cecc4e7c8188c2f92a4, title=正经叭叭)
    Podcast(pid=61791d921989541784257779, title=不开玩笑 Jokes Aside)

#### 12. 搜索单集¶

    cnt = 0
    async for episode in c.episode_search.search("2025"):
        print(episode)
        cnt += 1
        if cnt >= 5:
            break

    Episode(eid=6873dcc11317e91f3d8f9ed8, pid=5e280fac418a84a0461fb129, title=vol.533 老友聊聊｜2025悄悄过半，再不总结真记不住啦！)
    Episode(eid=685f7c4608d8fd858666e5c5, pid=67b92c728671d63e927d8eee, title=单独系列 - 2025下半年经济和市场展望)
    Episode(eid=6819fac3d8d622bb801bd343, pid=61dd99a47b29652ff572257b, title=vol.127.年报季中的真实中国2025)
    Episode(eid=68498a63096eb0bc79503c69, pid=61dd99a47b29652ff572257b, title=132.当过度思考的打工人遇上低欲望的时代)
    Episode(eid=6853fc0db3d7fd80a40cb5ee, pid=5e2831ed418a84a046231c00, title=#Bonus  逃离德黑兰 2025：一个中国人的战火逃生记)

#### 13. 搜索用户¶

    cnt = 0
    async for user in c.user_search.search("七个梦"):
        print(user)
        cnt += 1
        if cnt >= 5:
            break

    User(uid=5e50e0e3e3edfc2abb066657, nickname=七个梦)
    User(uid=66097132edce67104a10aeaf, nickname=有七个梦)
    User(uid=60d74289e0f5e723bbefe494, nickname=第七个梦)

#### 用完后，别忘了¶

    await c.close()