Create a structured reply to a ticket.
    
    :param int ticket_id: The ticket to reply to.
    :param content: ``str``, ``dict``, or iterator of ``(title, content``) pairs.
    :returns: ``(reply_id, reply_content)``.
423596
def reply_to_ticket(ticket_id, content, user_id=None):
    
    
    user_comment = None
    exc_type = None

    if isinstance(content, dict):
        content = sorted(content.iteritems())

    if not isinstance(content, basestring):
        parts = []
        for heading, part in content:
            
            # This one gets special cased into a Reply.
            if heading.lower() == 'user comment':
                user_comment = part

            # Mappings.
            if isinstance(part, dict):
                parts.append((heading, '\n'.join('%s = %r' % x
                    for x in sorted(part.iteritems())
                )))
            
            # Iterators.
            elif isinstance(part, (list, tuple)):
                
                # Exceptions.
                if (len(part) == 3 and
                    issubclass(part[0], Exception) and
                    isinstance(part[1], Exception) and
                    isinstance(part[2], types.TracebackType)
                ):
                    exc_type = part[0]
                    parts.append((heading, '\n'.join(traceback.format_exception(*part)).rstrip()))
                
                # Iterators.
                else:
                    parts.append((heading, '\n'.join('- %r' % x for x in part)))
            
            # The rest.
            else:
                parts.append((heading, str(part)))
        
        # Join the parts.
        content = '\n\n'.join('%s\n%s\n%s' % (heading, '=' * len(heading), part) for heading, part in parts)
    
    # Get the Shotgun and Project.
    # TODO: Somehow pass this in later.
    shotgun = get_shotgun()

    # Convert requested user ID to a login.
    if user_id:
        user = shotgun.find_one('HumanUser', [('id', 'is', user_id)], ['login'])
        if user:
            shotgun.config.sudo_as_login = user['login']

    # Make sure we do have a login.
    if not shotgun.config.sudo_as_login:
        user = shotgun.find_one('HumanUser', [('email', 'starts_with', os.getlogin() + '@')], ['login'])
        if user:
            shotgun.config.sudo_as_login = user['login']
    
    reply = None

    if user_comment:
        reply = shotgun.create('Reply', {
            'content': user_comment,
            'entity': {'type': 'Ticket', 'id': ticket_id},
        })

    if content.strip():
        with tempfile.NamedTemporaryFile(suffix='ticket-%d-reply.txt' % ticket_id) as fh:
            fh.write(content)
            fh.flush()
            shotgun.upload('Ticket', ticket_id, fh.name, 'attachments',
               display_name='Ticket-%d.%s.%s.txt' % (
                    ticket_id,
                    exc_type.__name__ if exc_type else 'details',
                    datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S'),
                ),
            )

    return reply and reply['id'], content
984555
def parse(self, ticket):
        
        if len(ticket) < self._min_ticket_size():
            raise TicketParseError(ticket, 'Invalid ticket length')

        digest_len = self._hash.digest_size * 2
        digest = ticket[:digest_len]

        try:
            time_len = 8
            time = int(ticket[digest_len:digest_len + time_len], 16)
        except:
            raise TicketParseError(ticket, 'Invalid time field')

        parts = ticket[digest_len + time_len:].split('!')
        if len(parts) != 3:
            raise TicketParseError(ticket, 'Missing parts')

        user_id = ulp.unquote(parts[0])
        tokens = ()
        if parts[1]:
            tokens = tuple((ulp.unquote(t) for t in parts[1].split(',')))

        user_data = ulp.unquote(parts[2])

        return TicketInfo(digest, user_id, tokens, user_data, time)
21253
def email(self, comment, content_object, request):
        
        if not self.email_notification:
            return

        send_comment_posted(comment, request)
781422
def create_comment(ticket_id, input, options = {})
      make_request("tickets/#{ticket_id}", ({:update => Zendesk::Main.to_xml('comment', input)}), options)
    end
1282757
def create_ticket_str(self, prefix=None):
        
        if not prefix:
            prefix = self.model.TICKET_PREFIX
        return "%s-%d-%s" % (prefix, int(time.time()),
                             get_random_string(length=self.model.TICKET_RAND_LEN))
1334798
def ticket_comment_attachment_redact(self, ticket_id, comment_id, attachment_id, data, **kwargs):
        ""
        api_path = "/api/v2/tickets/{ticket_id}/comments/{comment_id}/attachments/{attachment_id}/redact.json"
        api_path = api_path.format(ticket_id=ticket_id, comment_id=comment_id, attachment_id=attachment_id)
        return self.call(api_path, method="PUT", data=data, **kwargs)
515980
def email(self, comment, content_object, request):
        
        if not self.email_notification:
            return
        recipient_list = [manager_tuple[1] for manager_tuple in settings.MANAGERS]
        t = loader.get_template('comments/comment_notification_email.txt')
        c = Context({ 'comment': comment,
                      'content_object': content_object })
        subject = '[%s] New comment posted on "%s"' % (get_current_site(request).name,
                                                          content_object)
        message = t.render(c)
        send_mail(subject, message, settings.DEFAULT_FROM_EMAIL, recipient_list, fail_silently=True)
628020
async def RelationById(self, relation_ids):
        '''
        
        '''
        # map input types to rpc msg
        _params = dict()
        msg = dict(type='Uniter',
                   request='RelationById',
                   version=5,
                   params=_params)
        _params['relation-ids'] = relation_ids
        reply = await self.rpc(msg)
        return reply
1042436
def reply(self, text, markup=None, parse_mode=None):
        
        if markup is None:
            markup = {}

        return self.send_text(
            text,
            reply_to_message_id=self.message["message_id"],
            disable_web_page_preview="true",
            reply_markup=self.bot.json_serialize(markup),
            parse_mode=parse_mode,
        )
752023
def ticket_incidents(self, id, **kwargs):
        ""
        api_path = "/api/v2/tickets/{id}/incidents.json"
        api_path = api_path.format(id=id)
        return self.call(api_path, **kwargs)
963350
def bind(self, ticket, device_id, user_id):
        
        return self._post(
            'bind',
            data={
                'ticket': ticket,
                'device_id': device_id,
                'openid': user_id
            }
        )
23889
def reply(self, messageId, *messageParts):
        
        routingInfo = self._routingInfo.pop(messageId)
        self.send(routingInfo + [messageId, b''] + list(messageParts))
1019786
def _verified_content_type_from_id(content_type_id):
    # type: (int) -> ContentType
    
    try:
        return ContentType(content_type_id)
    except ValueError as error:
        raise UnknownIdentityError("Unknown content type {}".format(content_type_id), error)
1203854
def reply_to(self, message, text, **kwargs):
        
        return self.send_message(message.chat.id, text, reply_to_message_id=message.message_id, **kwargs)
579814
def send_text_message(self, user_id, content, kf_account=None):
        
        data = {
            "touser": user_id,
            "msgtype": "text",
            "text": {
                "content": content
            }
        }
        if kf_account is not None:
            data['customservice'] = {'kf_account': kf_account}
        return self.post(
            url="https://api.weixin.qq.com/cgi-bin/message/custom/send",
            data=data
        )
747962
def get_by_id(self, reply_id):
        '''
        
        '''
        reply = MReply.get_by_uid(reply_id)
        logger.info('get_reply: {0}'.format(reply_id))

        self.render('misc/reply/show_reply.html',
                    reply=reply,
                    username=reply.user_name,
                    date=reply.date,
                    vote=reply.vote,
                    uid=reply.uid,
                    userinfo=self.userinfo,
                    kwd={})
1183216
def ticket_comments(self, ticket_id, **kwargs):
        ""
        api_path = "/api/v2/tickets/{ticket_id}/comments.json"
        api_path = api_path.format(ticket_id=ticket_id)
        return self.call(api_path, **kwargs)