public void SendEvent(string clientContext, string eventId) { dynamic eventBundle = new DynamicJson(); // nothing to put in it SendBundle(clientContext, eventId, eventBundle); }
public void HandleRequest(ApiRequest request) { if (CurrentBook == null) { Debug.Fail("BL-836 reproduction?"); // ReSharper disable once HeuristicUnreachableCode request.Failed("CurrentBook is null"); return; } if (request.CurrentCollectionSettings == null) { Debug.Fail("BL-836 reproduction?"); // ReSharper disable once HeuristicUnreachableCode request.Failed("CurrentBook.CollectionSettings is null"); return; } var lastSegment = request.LocalPath().Split(new char[] { '/' }).Last(); switch (lastSegment) { case "test": request.PostSucceeded(); break; case "readerSettingsEditForbidden": request.ReplyWithText(_tcManager.OkToEditCollectionSettings ? "" : WorkspaceView.MustBeAdminMessage); break; case "readerToolSettings": if (request.HttpMethod == HttpMethods.Get) { request.ReplyWithJson(GetReaderSettings(request.CurrentBook.BookData)); } else { var path = DecodableReaderToolSettings.GetReaderToolsSettingsFilePath(request.CurrentCollectionSettings); var content = request.RequiredPostJson(); RobustFile.WriteAllText(path, content, Encoding.UTF8); request.PostSucceeded(); } break; //note, this endpoint is confusing because it appears that ultimately we only use the word list out of this file (see "sampleTextsList"). //This ends up being written to a ReaderToolsWords-xyz.json (matching its use, if not it contents). case "synphonyLanguageData": //This is the "post". There is no direct "get", but the name of the file is given in the "sampleTextList" reply, below. // We've had situations (BL-4313 and friends) where reading the posted data fails. This seems to be due to situations // where we have a very large block of data and are rapidly switching between books. But as far as I can tell, the only // case where it's at all important to capture the new language data is if the user has been changing settings and // in particular editing the word list. Timing out the save in that situation seems very unlikely to fail. // So, in the interests of preventing the crash when switching books fast, we will ignore failure to read all the // json, and just not update the file. We would in any case keep only the version of the data sent to us by // the last book which sends it, and that one is unlikely to get interrupted. string langdata; try { langdata = request.RequiredPostJson(); } catch (IOException e) { SIL.Reporting.Logger.WriteError("Saving synphonyLanguageData failed to get Json", e); break; } SaveSynphonyLanguageData(langdata); request.PostSucceeded(); break; case "sampleTextsList": //note, as part of this reply, we send the path of the "ReaderToolsWords-xyz.json" which is *written* by the "synphonyLanguageData" endpoint above request.ReplyWithText(GetSampleTextsList(request.CurrentCollectionSettings.SettingsFilePath)); break; case "sampleFileContents": request.ReplyWithText(GetTextFileContents(request.RequiredParam("fileName"), WordFileType.SampleFile)); break; case "textOfContentPages": request.ReplyWithText(GetTextOfContentPagesAsJson()); break; case "makeLetterAndWordList": MakeLetterAndWordList(request.RequiredPostString("settings"), request.RequiredPostString("allWords")); request.PostSucceeded(); break; case "openTextsFolder": OpenTextsFolder(); request.PostSucceeded(); break; case "chooseAllowedWordsListFile": lock (request) { request.ReplyWithText(ShowSelectAllowedWordsFileDialog()); } break; case "allowedWordsList": switch (request.HttpMethod) { case HttpMethods.Delete: RecycleAllowedWordListFile(request.RequiredParam("fileName")); request.PostSucceeded(); break; case HttpMethods.Get: var fileName = request.RequiredParam("fileName"); request.ReplyWithText(RemoveEmptyAndDupes(GetTextFileContents(fileName, WordFileType.AllowedWordsFile))); break; default: request.Failed("Http verb not handled"); break; } break; case "defaultLevel": if (request.HttpMethod == HttpMethods.Get) { request.ReplyWithText(Settings.Default.CurrentLevel.ToString()); } else { int level; if (int.TryParse(request.RequiredParam("level"), out level)) { Settings.Default.CurrentLevel = level; Settings.Default.Save(); } else { // Don't think any sort of runtime failure is worthwhile here. Debug.Fail("could not parse level number"); } request.PostSucceeded(); // technically it didn't if we didn't parse the number } break; case "defaultStage": if (request.HttpMethod == HttpMethods.Get) { request.ReplyWithText(Settings.Default.CurrentStage.ToString()); } else { int stage; if (int.TryParse(request.RequiredParam("stage"), out stage)) { Settings.Default.CurrentStage = stage; Settings.Default.Save(); } else { // Don't think any sort of runtime failure is worthwhile here. Debug.Fail("could not parse stage number"); } request.PostSucceeded(); // technically it didn't if we didn't parse the number } break; case "copyBookStatsToClipboard": // See https://issues.bloomlibrary.org/youtrack/issue/BL-10018. string bookStatsString; try { bookStatsString = request.RequiredPostJson(); dynamic bookStats = DynamicJson.Parse(bookStatsString); var headerBldr = new StringBuilder(); var dataBldr = new StringBuilder(); headerBldr.Append("Book Title"); var title = _bookSelection.CurrentSelection.Title; title = title.Replace("\"", "\"\""); // Double double quotes to get Excel to recognize them. dataBldr.AppendFormat("\"{0}\"", title); headerBldr.Append("\tLevel"); dataBldr.AppendFormat("\t\"Level {0}\"", bookStats["levelNumber"]); headerBldr.Append("\tNumber of Pages with Text"); dataBldr.AppendFormat("\t{0}", bookStats["pageCount"]); headerBldr.Append("\tTotal Number of Words"); dataBldr.AppendFormat("\t{0}", bookStats["actualWordCount"]); headerBldr.Append("\tTotal Number of Sentences"); dataBldr.AppendFormat("\t{0}", bookStats["actualSentenceCount"]); headerBldr.Append("\tAverage No of Words per Page with Text"); dataBldr.AppendFormat("\t{0:0.#}", bookStats["actualAverageWordsPerPage"]); headerBldr.Append("\tAverage No of Sentences per Page with Text"); dataBldr.AppendFormat("\t{0:0.#}", bookStats["actualAverageSentencesPerPage"]); headerBldr.Append("\tNumber of Unique Words"); dataBldr.AppendFormat("\t{0}", bookStats["actualUniqueWords"]); headerBldr.Append("\tAverage Word Length"); dataBldr.AppendFormat("\t{0:0.#}", bookStats["actualAverageGlyphsPerWord"]); headerBldr.Append("\tAverage Sentence Length"); dataBldr.AppendFormat("\t{0:0.#}", bookStats["actualAverageWordsPerSentence"]); headerBldr.Append("\tMaximum Word Length"); dataBldr.AppendFormat("\t{0}", bookStats["actualMaxGlyphsPerWord"]); headerBldr.Append("\tMaximum Sentence Length"); dataBldr.AppendFormat("\t{0}", bookStats["actualMaxWordsPerSentence"]); // "actualWordsPerPageBook" is the maximum number of words on a page in the book // It's in the json data, but not asked for in the clipboard copying. var stringToSave = headerBldr.ToString() + Environment.NewLine + dataBldr.ToString(); PortableClipboard.SetText(stringToSave); } catch (IOException e) { SIL.Reporting.Logger.WriteError("Copying book statistics to clipboard failed to get Json", e); break; } request.PostSucceeded(); break; default: request.Failed("Don't understand '" + lastSegment + "' in " + request.LocalPath()); break; } }