// EditMedia used to edit already sent media with known recepient and message id.
//
// Use cases:
//
//     bot.EditMedia(msg, &tb.Photo{File: tb.FromDisk("chicken.jpg")});
//     bot.EditMedia(msg, &tb.Video{File: tb.FromURL("http://video.mp4")});
//
199036
func (b *Bot) EditMedia(message Editable, inputMedia InputMedia, options ...interface{}) (*Message, error) {
	var mediaRepr string;
	var jsonRepr []byte;
	var thumb *Photo;

	file := make(map[string]File);

	f := inputMedia.MediaFile();

	if f.InCloud() {
		mediaRepr = f.FileID;
	} else if f.FileURL != "" {
		mediaRepr = f.FileURL;
	} else if f.OnDisk() || f.FileReader != nil {
		s := f.FileLocal;
		if (f.FileReader != nil) {
			s = "0";
		}
		mediaRepr = "attach://" + s;
		file[s] = *f;
	} else {
		return nil, errors.Errorf(
			"telebot: can't edit media, it doesn't exist anywhere");
	}

	type FileJson struct {
		// All types.
		Type              string `json:"type"`
		Caption           string `json:"caption"`
		Media             string `json:"media"`

		// Video.
		Width             int    `json:"width,omitempty"`
		Height            int    `json:"height,omitempty"`
		SupportsStreaming bool   `json:"supports_streaming,omitempty"`

		// Video and audio.
		Duration          int    `json:"duration,omitempty"`

		// Document.
		FileName          string `json:"file_name"`

		// Document, video and audio.
		Thumbnail         string `json:"thumb,omitempty"`
		MIME              string `json:"mime_type,omitempty"`

		// Audio.
		Title             string `json:"title,omitempty"`
		Performer         string `json:"performer,omitempty"`
	}

	resultMedia := &FileJson {Media: mediaRepr};

	switch y := inputMedia.(type) {
		case *Photo:
			resultMedia.Type = "photo";
			resultMedia.Caption = y.Caption;
		case *Video:
			resultMedia.Type = "video";
			resultMedia.Caption = y.Caption;
			resultMedia.Width = y.Width;
			resultMedia.Height = y.Height;
			resultMedia.Duration = y.Duration;
			resultMedia.SupportsStreaming = y.SupportsStreaming;
			resultMedia.MIME = y.MIME;
			thumb = y.Thumbnail;
			if thumb != nil {
				resultMedia.Thumbnail = "attach://thumb";
			}
		case *Document:
			resultMedia.Type = "document";
			resultMedia.Caption = y.Caption;
			resultMedia.FileName = y.FileName;
			resultMedia.MIME = y.MIME;
			thumb = y.Thumbnail;
			if thumb != nil {
				resultMedia.Thumbnail = "attach://thumb";
			}
		case *Audio:
			resultMedia.Type = "audio";
			resultMedia.Caption = y.Caption;
			resultMedia.Duration = y.Duration;
			resultMedia.MIME = y.MIME;
			resultMedia.Title = y.Title;
			resultMedia.Performer = y.Performer;
		default:
			return nil, errors.Errorf("telebot: inputMedia entry is not valid");
	}

	messageID, chatID := message.MessageSig();

	jsonRepr, _ = json.Marshal(resultMedia);
	params := map[string]string{};
	params["media"] = string(jsonRepr);

	// If inline message.
	if chatID == 0 {
		params["inline_message_id"] = messageID;
	} else {
		params["chat_id"] = strconv.FormatInt(chatID, 10);
		params["message_id"] = messageID;
	}

	if thumb != nil {
		file["thumb"] = *thumb.MediaFile();
	}

	sendOpts := extractOptions(options);
	embedSendOptions(params, sendOpts);

	respJSON, err := b.sendFiles("editMessageMedia", file, params);
	if err != nil {
		return nil, err;
	}

	return extractMsgResponse(respJSON);
}
632508
func (s *TranscriptionJob) SetMediaFormat(v string) *TranscriptionJob {
	s.MediaFormat = &v
	return s
}
165881
async def editMessageMedia(self, msg_identifier, media,
                               reply_markup=None):
        
        p = _strip(locals(), more=['msg_identifier'])
        p.update(_dismantle_message_identifier(msg_identifier))
        return await self._api_request('editMessageMedia', _rectify(p))
1263226
func (this *Weixinmp) ReplyImageMsg(rw http.ResponseWriter, mediaId string) error {
	var msg imageMsg
	msg.MsgType = "image"
	msg.Image.MediaId = mediaId
	return this.replyMsg(rw, &msg)
}
214035
func editRecord(c *godo.Client, zoneName string, recordID int, editRequest *godo.DomainRecordEditRequest) error {
	_, _, err := c.Domains.EditRecord(context.TODO(), zoneName, recordID, editRequest)
	if err != nil {
		return fmt.Errorf("error editing record: %v", err)
	}

	return nil
}
477249
func (m *Message) Append(s Session) Session {
	s = s.AddVersion(m.Version)
	s = s.AddOrigin(m.Origin)
	s = s.AddSessionName(m.Name)
	if len(m.Info) > 0 {
		s = s.AddSessionInfo(m.Info)
	}
	if len(m.URI) > 0 {
		s = s.AddURI(m.URI)
	}
	if len(m.Email) > 0 {
		s = s.AddEmail(m.Email)
	}
	if len(m.Phone) > 0 {
		s = s.AddPhone(m.Phone)
	}
	if !m.Connection.Blank() {
		s = s.AddConnectionData(m.Connection)
	}
	for t, v := range m.Bandwidths {
		s = s.AddBandwidth(t, v)
	}
	// One or more time descriptions ("t=" and "r=" lines)
	for _, t := range m.Timing {
		s = s.AddTiming(t.Start, t.End)
		if len(t.Offsets) > 0 {
			s = s.AddRepeatTimesCompact(t.Repeat, t.Active, t.Offsets...)
		}
	}
	if len(m.TZAdjustments) > 0 {
		s = s.AddTimeZones(m.TZAdjustments...)
	}
	if !m.Encryption.Blank() {
		s = s.AddEncryption(m.Encryption)
	}
	s = s.appendAttributes(m.Attributes)

	for i := range m.Medias {
		s = s.AddMediaDescription(m.Medias[i].Description)
		if len(m.Medias[i].Title) > 0 {
			s = s.AddSessionInfo(m.Medias[i].Title)
		}
		if !m.Medias[i].Connection.Blank() {
			s = s.AddConnectionData(m.Medias[i].Connection)
		}
		for t, v := range m.Medias[i].Bandwidths {
			s = s.AddBandwidth(t, v)
		}
		if !m.Medias[i].Encryption.Blank() {
			s = s.AddEncryption(m.Medias[i].Encryption)
		}
		s = s.appendAttributes(m.Medias[i].Attributes)
	}
	return s
}
1208469
func (d *Document) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) {
	params := map[string]string{
		"chat_id": to.Recipient(),
		"caption": d.Caption,
	}

	if d.FileSize != 0 {
		params["file_size"] = strconv.Itoa(d.FileSize)
	}

	embedSendOptions(params, opt)

	msg, err := b.sendObject(&d.File, "document", params, thumbnailToFilemap(d.Thumbnail))
	if err != nil {
		return nil, err
	}

	msg.Document.File.stealRef(&d.File)
	*d = *msg.Document

	return msg, nil
}
294058
func (p *MasterPlaylist) Append(uri string, chunklist *MediaPlaylist, params VariantParams) {
	v := new(Variant)
	v.URI = uri
	v.Chunklist = chunklist
	v.VariantParams = params
	p.Variants = append(p.Variants, v)
	if len(v.Alternatives) > 0 {
		// From section 7:
		// The EXT-X-MEDIA tag and the AUDIO, VIDEO and SUBTITLES attributes of
		// the EXT-X-STREAM-INF tag are backward compatible to protocol version
		// 1, but playback on older clients may not be desirable.  A server MAY
		// consider indicating a EXT-X-VERSION of 4 or higher in the Master
		// Playlist but is not required to do so.
		version(&p.ver, 4) // so it is optional and in theory may be set to ver.1
		// but more tests required
	}
	p.buf.Reset()
}
1212993
func EditPost(client ClientInterface, blogName string, postId uint64, params url.Values) error {
	_, err := client.PostWithParams(blogPath("/blog/%s/post/edit", blogName), setPostId(postId, params))
	return err
}
347527
func (c *Corpus) mergeMediaTag(k, v []byte) error {
	f := strings.Split(string(k), "|")
	if len(f) != 3 {
		return fmt.Errorf("unexpected key %q", k)
	}
	wholeRef, ok := blob.Parse(f[1])
	if !ok {
		return fmt.Errorf("failed to parse wholeref from key %q", k)
	}
	tm, ok := c.mediaTags[wholeRef]
	if !ok {
		tm = make(map[string]string)
		c.mediaTags[wholeRef] = tm
	}
	tm[c.str(f[2])] = c.str(urld(string(v)))
	return nil
}
586922
func (model *Model) EditsMulti(term string, depth int) []string {
	edits := Edits1(term)
	for {
		depth--
		if depth <= 0 {
			break
		}
		for _, edit := range edits {
			edits2 := Edits1(edit)
			for _, edit2 := range edits2 {
				edits = append(edits, edit2)
			}
		}
	}
	return edits
}
208068
func FormatFromMediaType(mt string, params map[string]string) (Format, error) {
	switch mt {
	case ContentTypePRPC:
		for k := range params {
			if k != mtPRPCEncoding {
				return 0, fmt.Errorf("unexpected parameter %q", k)
			}
		}
		return FormatFromEncoding(params[mtPRPCEncoding])

	case ContentTypeJSON:
		return FormatJSONPB, nil

	case "", "*/*", "application/*", "application/grpc":
		return FormatBinary, nil

	default:
		return 0, fmt.Errorf("unknown content type: %q", mt)
	}
}
434090
func IsMultipartMessage(mailMsg *mail.Message) bool {
	// Parse top-level multipart
	ctype := mailMsg.Header.Get("Content-Type")
	mediatype, _, err := mime.ParseMediaType(ctype)
	if err != nil {
		return false
	}
	// According to rfc2046#section-5.1.7 all other multipart should
	// be treated as multipart/mixed
	return strings.HasPrefix(mediatype, "multipart/")
}
502545
func (c *Context) EditMessageTextAndInlineKeyboard(om *OutgoingMessage, fromState string, text string, kb InlineKeyboard) error {
	bot := c.Bot()
	if om.MsgID != 0 {
		log.WithField("msgID", om.MsgID).Debug("EditMessageTextAndInlineKeyboard")
	} else {
		om.ChatID = 0
		log.WithField("inlineMsgID", om.InlineMsgID).Debug("EditMessageTextAndInlineKeyboard")
	}

	var msg OutgoingMessage

	var err error

	if om.ParseMode == "HTML" {
		textCleared, err := sanitize.HTMLAllowing(text, []string{"a", "b", "strong", "i", "em", "a", "code", "pre"}, []string{"href"})

		if err == nil && textCleared != "" {
			text = textCleared
		}
	}

	om.Text = text
	prevTextHash := om.TextHash
	om.TextHash = om.GetTextHash()

	if fromState != "" {
		_, err = c.db.C("messages").Find(bson.M{"_id": om.ID, "$or": []bson.M{{"inlinekeyboardmarkup.state": fromState}, {"inlinekeyboardmarkup": bson.M{"$exists": false}}}}).Apply(mgo.Change{Update: bson.M{"$set": bson.M{"inlinekeyboardmarkup": kb, "texthash": om.TextHash}}}, &msg)
	} else {
		_, err = c.db.C("messages").Find(bson.M{"_id": om.ID}).Apply(mgo.Change{Update: bson.M{"$set": bson.M{"inlinekeyboardmarkup": kb, "texthash": om.TextHash}}}, &msg)
	}

	if err != nil {
		c.Log().WithError(err).Error("EditMessageTextAndInlineKeyboard messages update error")
	}

	if msg.BotID == 0 {
		c.Log().Warn(fmt.Sprintf("EditMessageTextAndInlineKeyboard – message (_id=%s botid=%v id=%v state %s) not found", om.ID.Hex(), bot.ID, om.MsgID, fromState))
		return nil

	}

	tgKeyboard := kb.tg()

	if prevTextHash == om.TextHash {
		prevTGKeyboard := om.InlineKeyboardMarkup.tg()
		if whetherTGInlineKeyboardsAreEqual(prevTGKeyboard, tgKeyboard) {
			c.Log().Debugf("EditMessageTextAndInlineKeyboard – message (_id=%s botid=%v id=%v state %s) not updated both text and kb have not changed", om.ID.Hex(), bot.ID, om.MsgID, fromState)
			return nil
		}
	}


	_, err = bot.API.Send(tg.EditMessageTextConfig{
		BaseEdit: tg.BaseEdit{
			ChatID:          om.ChatID,
			InlineMessageID: om.InlineMsgID,
			MessageID:       om.MsgID,
			ReplyMarkup:     &tg.InlineKeyboardMarkup{InlineKeyboard: tgKeyboard},
		},
		ParseMode: om.ParseMode,
		Text:      text,
		DisableWebPagePreview: !om.WebPreview,
	})

	if err != nil {
		if err.(tg.Error).IsCantAccessChat() || err.(tg.Error).ChatMigrated() {
			if c.Callback != nil {
				c.AnswerCallbackQuery("Message can be outdated. Bot can't edit messages created before converting to the Super Group", false)
			}
		} else if err.(tg.Error).IsAntiFlood() {
			c.Log().WithError(err).Warn("TG Anti flood activated")
		}
		// Oops. error is occurred – revert the original keyboard
		c.db.C("messages").Update(bson.M{"_id": msg.ID}, bson.M{"$set": bson.M{"texthash": prevTextHash, "inlinekeyboardmarkup": msg.InlineKeyboardMarkup}})
		return err
	}

	return nil
}
261139
func (api *Client) DeleteMediaFile(name string) error {
	_, _, err := api.makeRequest(http.MethodDelete, fmt.Sprintf("%s/%s", api.concatUserPath(mediaPath), url.QueryEscape(name)))
	return err
}
143595
func NewVideoMessage(originalContentURL, previewImageURL string) *VideoMessage {
	return &VideoMessage{
		OriginalContentURL: originalContentURL,
		PreviewImageURL:    previewImageURL,
	}
}
630148
func FormatFromMediaType(m media.Type) Format {
	for _, suffix := range m.Suffixes {
		if f := FormatFromString(suffix); f != "" {
			return f
		}
	}

	return ""
}