Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Frontend tweaks, split help text into multiple topics rather than bombarding the user with messages |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
76166a5ce733bb042eb1c332fe980566 |
User & Date: | murphy 2020-04-29 09:34:56.000 |
Context
2020-04-29
| ||
11:51 | Corrected command recognition pattern check-in: e9bc359947 user: murphy tags: trunk | |
09:34 | Frontend tweaks, split help text into multiple topics rather than bombarding the user with messages check-in: 76166a5ce7 user: murphy tags: trunk | |
2020-04-28
| ||
23:03 | Corrected computation of race without subrace check-in: 58a729d0be user: murphy tags: trunk | |
Changes
Changes to DragonDice.Bot/Session.fs.
︙ | ︙ | |||
168 169 170 171 172 173 174 | /// Evaluate a command sent to the bot. member __.AsyncEval(user:User, args:List<string>) : Async<CommandResult> = async { match args with | ["/start" | "/help"] -> return Markup ( | | | > > > > > > > > | > > > > > > > | | > > > > > > > > > > > > | | 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 | /// Evaluate a command sent to the bot. member __.AsyncEval(user:User, args:List<string>) : Async<CommandResult> = async { match args with | ["/start" | "/help"] -> return Markup ( "I can manage characters, simulate dice rolls and compute statistical estimates for you. Choose one of the topics below to learn more.", [ ["Dice Rolls", "roll"] ["Character State", "state"] ["Character Design", "create"] ] ) | ["/start" | "/help"; "roll"] -> return Markup ( """<b>Dice Rolls:</b> /roll <i>N</i>d<i>S</i> [+- <i>D</i>] — Roll <i>N</i> <i>S</i>-sided dice and add / subtract <i>D</i> to / from the total. /estimate <i>N</i>d<i>S</i> [+- <i>D</i>] — Estimate the result of rolling <i>N</i> <i>S</i>-sided dice and adding / subtracting <i>D</i> to / from the total. <b>Ability Checks:</b> /roll <i>ABILITY</i> [+- <i>D</i>] [, <i>OPTION</i>] — Roll a 20-sided die, add / subtract the ability modifier and <i>D</i>, and compare with <i>DC</i>. /estimate <i>ABILITY</i> [+- <i>D</i>] [, <i>OPTION</i>] — Estimate the result of rolling a 20-sided die, adding / subtracting the ability modifier and <i>D</i>, and comparing with <i>DC</i>. <b>Skill Checks:</b> /roll <i>SKILL</i> [, <i>OPTION</i>] — Roll a 20-sided die, add / subtract the skill and ability modifiers, and compare with <i>DC</i>. /passive <i>SKILL</i> [, dc|difficulty <i>DC</i>] — Determine the passive score using the skill and ability modifiers, and compare with <i>DC</i>. /estimate <i>SKILL</i> [, <i>OPTION</i>] — Estimate the result of rolling a 20-sided die, adding / subtracting the skill and ability modifiers, and comparing with <i>DC</i>. /spellsave <i>SKILL</i> — Determine the spell save DC using the skill and ability modifiers of a magic skill. /proficiency — Determine the proficiency bonus of the active character. <b>Check Options:</b> dc|difficulty <i>DC</i> — The <i>DC</i> of an ability or skill check may be specified as a number or it may be one of the adjectives <i>Very Easy</i>, <i>Easy</i>, <i>Medium</i>, <i>Hard</i>, <i>Very Hard</i>, or <i>Impossible</i>. ins[piration] d<i>S</i> — An <i>S</i>-sided inspiration die may be added to a check. If multiple of these options are given, the highest <i>S</i> is used. adv[antage]|dis[advantage]|normal — Checks may be performed at advantage, disadvantage or normal conditions. If multiple of these options are specified, the majority of advantage or disadvantage options determines the conditions. /help — Back to Contents """, List.empty ) | ["/start" | "/help"; "state"] -> return Markup ( """<b>Character State:</b> /select [<i>NAME</i>] — Select the active character for the user who is asking. /show|stat|state|stats — Display a summary of the active character's statistics. /talk — Display the set of common languages for all the active characters selected in the conversation. /heal <i>HP</i> — Restore <i>HP</i> hit points up to the maximum of the active character. /hurt|damage <i>HP</i> [, <i>DAMAGE</i>] — Deal <i>HP</i> damage to the active character. If a damage type is specified, the character's defenses may apply. /bolster <i>HP</i> — Add temporary hit points to the active character. /rest[ore] — Restore hit points to maximum and remove temporary hit points from the active character. /gain <i>GP</i> — Add an amount of currency to the active character. /spend <i>GP</i> — Remove an amount of currency to the active character. <b>Hit Points:</b> The <i>HP</i> argument to the health management commands may be a dice roll specification or a constant non-negative integer. <b>Currency:</b> The <i>GP</i> argument to the currency management commands may be an amount suffixed with <i>cp</i>, <i>sp</i>, <i>ep</i>, <i>gp</i>, or <i>pp</i>. <b>Character Storage:</b> /save — Save the active character. /reload <i>NAME</i> — Reload the active character. To confirm, the name must match. /delete <i>NAME</i> — Delete the active character. To confirm, the name must match. /help — Back to Contents """, List.empty ) | ["/start" | "/help"; "create"] -> return Markup ( """<b>Character Design:</b> /create [<i>NAME</i>] — Create a new character and select it for the user who is asking. /open5e <i>QUERY</i> — Import a new character from Open5e and select it for the user who is asking. /setname <i>NAME</i> — Change the name of the active character. /setrace <i>RACE</i> — Change the race of the active character. This operation does not work on imported characters. /set ac =|+=|-= <i>N</i> — Change the armor class of the active character. /set hp =|+=|-= <i>N</i> — Change the maximum hit points of the active character. /set <i>SPEED</i> =|+=|-= <i>N</i> — Change a movement speed of the active character. |
︙ | ︙ | |||
231 232 233 234 235 236 237 238 239 240 241 242 243 244 | /addlanguage <i>NAME</i> — Add a language proficiency to the active character. /removelanguage <i>NAME</i> — Remove a language proficiency from the active character. <b>Character Storage:</b> /save — Save the active character. /reload <i>NAME</i> — Reload the active character. To confirm, the name must match. /delete <i>NAME</i> — Delete the active character. To confirm, the name must match. """, List.empty ) | ["/roll" | "/estimate"] -> let dup x = x, x return Markup ( | > > | 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 | /addlanguage <i>NAME</i> — Add a language proficiency to the active character. /removelanguage <i>NAME</i> — Remove a language proficiency from the active character. <b>Character Storage:</b> /save — Save the active character. /reload <i>NAME</i> — Reload the active character. To confirm, the name must match. /delete <i>NAME</i> — Delete the active character. To confirm, the name must match. /help — Back to Contents """, List.empty ) | ["/roll" | "/estimate"] -> let dup x = x, x return Markup ( |
︙ | ︙ | |||
439 440 441 442 443 444 445 | | ["/proficiency"] -> let chr = selectedCharacter user return Markup ( sprintf "<i>%s</i> : Proficiency Bonus = <b>%+d</b>" (HttpUtility.HtmlEncode chr.Name) chr.ProficiencyBonus, List.empty ) | | | 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 | | ["/proficiency"] -> let chr = selectedCharacter user return Markup ( sprintf "<i>%s</i> : Proficiency Bonus = <b>%+d</b>" (HttpUtility.HtmlEncode chr.Name) chr.ProficiencyBonus, List.empty ) | ["/show" | "/stat" | "/state" | "/stats"] -> let chr = selectedCharacter user let buffer = Text.StringBuilder(1024) buffer .Append("<b>Name:</b> ").Append(HttpUtility.HtmlEncode chr.Name).Append('\n') .Append("<i>").Append(HttpUtility.HtmlEncode chr.Race) |> ignore if not (String.IsNullOrEmpty chr.Profession) then |
︙ | ︙ |
Changes to DragonDice.Bot/Worker.fs.
︙ | ︙ | |||
83 84 85 86 87 88 89 | let sendReply (bot:TelegramBotClient) (ssn:Session) (qid:int) (cmd:List<string>) (reply:Choice<CommandResult, exn>) = async { let tag = replyTag reply let! stop = Async.CancellationToken let! reply = match reply with | Choice1Of2 (Markup (html, buttons)) -> | < < < | < < < < < < < < < < < < | | | | | 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | let sendReply (bot:TelegramBotClient) (ssn:Session) (qid:int) (cmd:List<string>) (reply:Choice<CommandResult, exn>) = async { let tag = replyTag reply let! stop = Async.CancellationToken let! reply = match reply with | Choice1Of2 (Markup (html, buttons)) -> bot.SendTextMessageAsync( ssn.ChatId, html, ParseMode.Html, replyMarkup = makeInlineKeyboard buttons, cancellationToken = stop ) |> Async.AwaitTask | Choice1Of2 (Figure (bitmap, caption)) -> let data = new IO.MemoryStream() bitmap.Save(data, Imaging.ImageFormat.Png) data.Position <- 0L bot.SendPhotoAsync( ssn.ChatId, InputMedia(data, "figure.png"), caption, ParseMode.Html, cancellationToken = stop |
︙ | ︙ | |||
133 134 135 136 137 138 139 | async { let tag = replyTag reply let! stop = Async.CancellationToken if fst info.ReplyId = tag then let rid = snd info.ReplyId match reply with | Choice1Of2 (Markup (html, buttons)) -> | < < | < < < < < < < < < < < < | | | | | 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | async { let tag = replyTag reply let! stop = Async.CancellationToken if fst info.ReplyId = tag then let rid = snd info.ReplyId match reply with | Choice1Of2 (Markup (html, buttons)) -> bot.EditMessageTextAsync( ssn.ChatId, rid, html, ParseMode.Html, replyMarkup = makeInlineKeyboard buttons, cancellationToken = stop ) |> ignore | Choice1Of2 (Figure (bitmap, caption)) -> let data = new IO.MemoryStream() bitmap.Save(data, Imaging.ImageFormat.Png) data.Position <- 0L bot.EditMessageMediaAsync( ssn.ChatId, rid, InputMediaPhoto(InputMedia(data, "figure.png"), Caption = caption, ParseMode = ParseMode.Html), |
︙ | ︙ | |||
176 177 178 179 180 181 182 | ssn.Replies.[info.QueryId] <- info ssn.Replies.[rid] <- info else let del = bot.DeleteMessageAsync(ssn.ChatId, snd info.ReplyId, cancellationToken = stop) let! reply = match reply with | Choice1Of2 (Markup (html, buttons)) -> | < < < | < < < < < < < < < < < < | | | | | 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | ssn.Replies.[info.QueryId] <- info ssn.Replies.[rid] <- info else let del = bot.DeleteMessageAsync(ssn.ChatId, snd info.ReplyId, cancellationToken = stop) let! reply = match reply with | Choice1Of2 (Markup (html, buttons)) -> bot.SendTextMessageAsync( ssn.ChatId, html, ParseMode.Html, replyMarkup = makeInlineKeyboard buttons, cancellationToken = stop ) |> Async.AwaitTask | Choice1Of2 (Figure (bitmap, caption)) -> let data = new IO.MemoryStream() bitmap.Save(data, Imaging.ImageFormat.Png) data.Position <- 0L bot.SendPhotoAsync( ssn.ChatId, InputMedia(data, "figure.png"), caption, ParseMode.Html, cancellationToken = stop |
︙ | ︙ |