Spaces:
Paused
Paused
File size: 6,153 Bytes
61d6e2a 848377f 61d6e2a 848377f 61d6e2a 848377f 61d6e2a 848377f 61d6e2a 109b8ca 61d6e2a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | import asyncio
from app.tgutil import button_url
from .harness import App, norm
SEEDED = [[{"t": "Download Episodes 01 to 20", "u": "https://t.me/oldbot?start=aaa"}]]
async def make_app(tmp_path):
app = App(tmp_path)
await app.start()
await app.db.save_channel(1, 5, "Anime Channel", "animech", 1)
return app
def sent_markup(app, i=-1):
return app.tg.sent[i][3]["buttons"]
def test_suggestion_flow_end_to_end(tmp_path):
async def run():
app = await make_app(tmp_path)
await app.db.create_post(channel_id=1, message_id=10, status="sent", source="bot", text="Click the button below to download ๐", entities=[], buttons=SEEDED)
await app.text("/new")
assert "Suggestion" in app.out.last_text and "Download Episodes 21 to 40" in app.out.last_text
await app.press(app.out.callback_data("Use suggestion"))
assert "Send the link" in app.out.last_text
await app.text("https://t.me/newbot?start=zzz")
assert "Ready" in app.out.last_text and "Publish" in str(app.out.last_buttons())
pid = int(app.out.callback_data("Publish").split(":")[1])
await app.press(f"pb:{pid}")
assert "Publish this post" in app.out.last_text
await app.press(f"pby:{pid}")
assert "Published" in app.out.last_text
kind, peer, msg, kw = app.tg.sent[-1]
assert msg == "Click the button below to download ๐"
btn = sent_markup(app).rows[0].buttons[0]
assert btn.text == "Download Episodes 21 to 40" and button_url(btn) == "https://t.me/newbot?start=zzz"
p = await app.db.get_post(pid)
assert p.status == "sent" and p.message_id == 100
# the next suggestion moves on again
await app.text("/new")
assert "Download Episodes 41 to 60" in app.out.last_text
await app.db.close()
asyncio.run(run())
def test_customize_new_post_with_buttons_and_edit_live(tmp_path):
async def run():
app = await make_app(tmp_path)
await app.text("/new") # nothing to suggest yet -> asks for the post
assert "Send the post now" in app.out.last_text
await app.text("Hello *world*") # typed as Markdown: read as formatting (MARKUP_INPUT=false would keep it literal)
assert "buttons" in app.out.last_text.lower()
await app.text("Get it - https://t.me/bot?start=1 | Join - t.me/animech\nMirror - https://example.com/x")
pid = int(app.out.callback_data("Publish").split(":")[1])
post = await app.db.get_post(pid)
assert post.text == "Hello world" and post.entities == [{"k": "italic", "o": 6, "l": 5}]
assert [len(r) for r in post.buttons] == [2, 1]
await app.press(f"pb:{pid}")
await app.press(f"pby:{pid}")
assert app.tg.sent[-1][2] == "Hello world"
# edit the live post: change a button's text, then its link
await app.press(f"bs:{pid}:0:0")
assert "Get it" in app.out.last_text
await app.press(f"bt:{pid}:0:0")
await app.text("Download now")
await app.press(f"bu:{pid}:0:0")
await app.text("https://t.me/goku?start=1")
last_edit = app.tg.edits[-1][2]
assert last_edit.message == "Hello world"
b = last_edit.reply_markup.rows[0].buttons[0]
assert b.text == "Download now" and button_url(b) == "https://t.me/goku?start=1"
# reorder: move the first button right, then down into its own row
await app.press(f"bm:{pid}:0:0:r")
rows = (await app.db.get_post(pid)).buttons
assert [b["t"] for b in rows[0]] == ["Join", "Download now"]
await app.press(f"bm:{pid}:0:1:d")
rows = (await app.db.get_post(pid)).buttons
assert [[b["t"] for b in r] for r in rows] == [["Join"], ["Mirror", "Download now"]]
# delete a button
await app.press(f"bd:{pid}:0:0")
assert [[b["t"] for b in r] for r in (await app.db.get_post(pid)).buttons] == [["Mirror", "Download now"]]
live = app.tg.edits[-1][2].reply_markup
assert [b.text for b in live.rows[0].buttons] == ["Mirror", "Download now"]
# edit text of the live post keeps the buttons
await app.press(f"et:{pid}")
await app.text("New text")
req = app.tg.edits[-1][2]
assert req.message == "New text" and len(req.reply_markup.rows[0].buttons) == 2
# delete from the channel
await app.press(f"dly:{pid}:a")
assert app.tg.deleted == [[100]] and await app.db.get_post(pid) is None
await app.db.close()
asyncio.run(run())
def test_bad_input_and_permissions(tmp_path):
async def run():
app = await make_app(tmp_path)
await app.text("/new")
await app.text("A post")
await app.text("this has no link")
assert "No link found" in norm(app.out.last_text)
await app.text("/skip")
pid = int(app.out.callback_data("Publish").split(":")[1])
await app.press(f"ba:{pid}")
await app.text("Only text") # asks for the link next
assert "send the link" in app.out.last_text.lower()
await app.text("not a link")
assert "doesn't look like a link" in norm(app.out.last_text)
await app.text("https://t.me/bot?start=q")
assert (await app.db.get_post(pid)).buttons[0][0]["u"] == "https://t.me/bot?start=q"
# a non-owner is rejected everywhere
app.uid = 999
await app.text("/swap @a @b")
assert "private" in app.out.last_text.lower()
await app.db.close()
asyncio.run(run())
def test_drafts_list_and_discard(tmp_path):
async def run():
app = await make_app(tmp_path)
await app.text("/new")
await app.text("draft one")
await app.text("/skip")
await app.text("/posts")
await app.press("pc:d:0")
assert "Drafts" in app.out.last_text and "draft one" in str(app.out.last_buttons())
pid = int(app.out.callback_data("draft one").split(":")[1])
await app.press(f"dly:{pid}:b")
assert await app.db.get_post(pid) is None
await app.db.close()
asyncio.run(run())
|