2016-06-25 52 views
0

我目前正在研究Telegram機器人,最近我幾乎完成它的敏感部分,現在我想激活webhook ,但webhook要求我在證書文件被激活前發送證書文件,之後我可能想爲我們的客戶發送一個文件,或者以文件形式接收他們的回覆(因爲我們希望通過文件激活我們的網站功能電報)。如何使用POCO將電文傳入和傳出電報(我不想使用任何中間件)

這裏是一個電報機器人的API參考: https://core.telegram.org/bots/api#inputfile

我自己,做了所有我通過API調用的HttpClient類,我希望繼續,因爲它是。 這裏是我的失敗方法:

public static Exception SetWebhook(SetWebhook webhook) 
    { 
     try 
     { 
      using (var hc = new HttpClient()) 
      { 
       HttpContent requestContent = new ObjectContent(typeof(SetWebhook), webhook, 
        new JsonMediaTypeFormatter 
        { 
         SerializerSettings = new JsonSerializerSettings 
         { 
          ContractResolver = new CustomPropertyNamesContractResolver 
          { 
           Case = IdentifierCase.UnderscoreSeparator 
          }, 
          NullValueHandling = NullValueHandling.Ignore 
         }, 
         SupportedEncodings = {Encoding.UTF8} 
        }, "multipart/form-data"); 

       var responseMessage = 
        hc.PostAsync("https://api.telegram.org/bot" + AppSetting.Token + "/setWebhook", 
         requestContent).Result; 

       if (responseMessage.IsSuccessStatusCode) 
       { 
        return null; 
       } 
       else 
       { 
        return new Exception("Status Code: " + responseMessage.StatusCode + "\n\nRequest" + responseMessage.RequestMessage.ToString() + "\n\nResponse" + responseMessage.ToString()); 
       } 
      } 
     } 
     catch (Exception ex) 
     { 
      return ex; 
     } 
    } 

這裏是我的模型: 由於電報沒有定義證書確切類型,我來看看這個:https://github.com/MrRoundRobin/telegram.bot生成它。

public class SetWebhook 
{ 
    /// <summary> 
    /// Optional<br/> 
    /// If empty remove webhook 
    /// </summary> 
    public string Url { get; set; } 

    /// <summary> 
    /// Optional<br/> 
    /// Upload your public key certificate so that the root certificate in use can be checked. See our self-signed guide for details. 
    /// </summary> 
    public InputFile Certificate { get; set; } 
} 

/// <summary> 
/// Represents information for a file to be sent 
/// </summary> 
public class InputFile 
{ 
    /// <summary> 
    /// Required <b/> 
    /// Gets or sets the filename. 
    /// </summary> 
    public string Filename { get; set; } 

    /// <summary> 
    /// Required <b/> 
    /// Gets or sets the content. 
    /// </summary> 
    public Stream Content { get; set; } 

    public InputFile() 
    { 
    } 

    /// <summary> 
    /// Initializes a new instance of the <see cref="InputFile"/> class. 
    /// </summary> 
    /// <param name="filename">The <see cref="Filename"/>.</param> 
    /// <param name="content">The <see cref="Content"/>.</param> 
    public InputFile(string filename, Stream content) 
    { 
     Filename = filename; 
     Content = content; 
    } 
} 

,這裏是我叫它方式:

public ActionResult SetWebhook() 
    { 
     var result = true; 
     var text = "-"; 

     try 
     { 
      WebHook.SetWebhook("http://ravis.ir:444/Data/Message", Server.MapPath("~/Files/ravis.ir-PEM.cer")); 
     } 
     catch(Exception ex) 
     { 

      result = false; 
      text = ex.Message; 
     } 

     return View(new WebhookResult 
     { 
      Result = result, 
      Text = text 
     }); 
    } 

這最後的辦法,錯誤:

((ex.InnerException).InnerException).Message - > 超時不支持此流。

(ex.InnerException).Message - > 錯誤從 'System.IO.FileStream' 'ReadTimeout' 得到的值。

ex.Message - > 發生了一個或多個錯誤。

那麼我該如何發送文件?我應該如何接收他們?我應該定義什麼樣的實體才能更準確?

回答

1

爲了得到這個工作,你應該建立MultipartFormDataContentStreamContent內(而不是ObjectContent):

using (var httpClient = new HttpClient()) 
using (var form = new MultipartFormDataContent()) 
{ 
    var content = new StreamContent(setWebhook.Certificate.Content); 
    form.Add(content, "certificate", setWebhook.Certificate.Filename); 
    form.Add(new StringContent(setWebhook.Url, Encoding.UTF8), "url"); 

    var response = await httpClient.PostAsync(uri, form); 
} 

至於接收文件 - 首先,你應該得到「文件信息」包含file_path,然後它可以下載:

var fileId = "fileId"; 

using (var httpClient = new HttpClient()) 
{ 
    var responseMessage = await httpClient.PostAsJsonAsync("https://api.telegram.org/bot" + token + "/getFile", new { file_id = fileId }); 
    responseMessage.EnsureSuccessStatusCode(); 
    var fileInfoResponse = await responseMessage.Content.ReadAsAsync<TelegramResponse<FileInfo>>(); 

    var fileUri = new Uri("https://api.telegram.org/file/bot" + token + "/" + fileInfoResponse.result.file_path); 
    var fileStreamResponse = await httpClient.GetAsync(fileUri, HttpCompletionOption.ResponseHeadersRead); 
    //and here's downloaded file 
    var stream = await fileStreamResponse.Content.ReadAsStreamAsync(); 
} 

這裏TelegramResponseFileInfo看起來索姆像這樣(*不是C#約定,但你可以修復這個如果你想):

class TelegramResponse<T> 
{ 
    public bool ok { get; set; } 
    public T result { get; set; } 
} 
class FileInfo 
{ 
    public string file_path { get; set; } 
} 
+0

非常感謝。接收文件怎麼樣?因爲我提到我需要發送和接收。 – deadManN

+0

你嘗試過什麼而不工作? –

+0

現在我並不需要傳輸文件,但是很快我就會需要,現在我只需要將它傳輸給webhooks,但這種方法沒有奏效。 (你的代碼,我還沒有測試它,今天早上有事要做,現在就來試試吧) – deadManN

相關問題