Rename Topic using API


(Valya Barboy) #1

Hello @team

I’ve been trying to rename topics via the API.
I’ve looked at the API docs and the code in GitHub, and I can’t seem to make the request.
Things I’ve tried:
‘http://{discourse-url}/t/{topic-slug}/{topic-id}’ with the new title, api_key, and api_username in JSON
’http://{discourse-url}/t/{topic-slug}/{topic-id}’ with the new title, api_key, and api_username as form data
’http://{discourse-url}/t/{topic-slug}/{topic-id}’ with the new title as JSON, and api_key, and api_username as form data
’http://{discourse-url}/t/{topic-slug}/{topic-id}’ with the new title as JSON (or form data), and api_key, and api_username as headers

I’ve also tried just using ‘http://{discourse-url}/t/{topic-id}.json’ with the various arrangements of the data. I have also tried looking at the chrome developer tools and trying to mimic that call (even copying and pasting the token instead of using the api key and username).

No matter what I try, I either get a “BAD CSRF” error, or am told that I don’t have the correct access rights to view the page.

I have not had trouble with other API requests using the same key and username (making topics, making categories, renaming/changing categories).

I would really appreciate some help here as I’ve been stuck with this for a few days now.

Thanks!


(Blake Erickson) #2

In situations like these I find it very helpful to install postman to minimize any content-type errors or authorization headers that can be hard to debug sometimes.

To rename a topic send a PUT request to http://discourse.example.com/t/-/1.json (you can just use a hyphen for the slug, instead of the actual slug, but it can’t be blank). In the body of your PUT quest include the api_key, api_username, and title. Send it with content-type form-data.


(Valya Barboy) #3

That seems to have worked. Thank you so much!


(Valya Barboy) #4

Not totally on the same topic, but since I have you – are there ways to reset the max length of a category name? It seems to be set to 50 but I’d like to allow mine to be longer. (@team, @blake)


(Valya Barboy) #5

This works from Postman (Dropbox - Screenshot 2017-07-17 17.15.08.png) but not when I try to do it from code. What am I doing wrong here?
@blake

            headers = {
                'Content-Type': 'multipart/form-data',
                'Cache-Control': 'no-cache'
            }
            data = {
                'api_key': os.getenv('DISCOURSE_API_KEY'),
                'api_username': os.getenv('DISCOURSE_API_USERNAME'),
                'title': instance.title
            }

            url_string = 'http://bbhalfdome.trydiscourse.com/t/{slug}/{id}' \
                .format(slug=discourse_thread.discourse_thread_slug,
                        id=discourse_thread.discourse_thread_id)
            result = requests.put(url_string, headers=headers, data=data)

(Blake Erickson) #6

I don’t think there is a way to increase it passed 50. I believe this is because there are many places in the UI that we show the category name and so the UI just will not look or work very well with long category names.

I’m not sure. Can you try hardcoding all your python variables to valid strings so that we can rule out any issues with populating the variables.


(Valya Barboy) #7

The variables work for other API calls (creating categories and topics) so I think we can rule that out.


(Blake Erickson) #8

Next time can you please include any error messages you have. What is the response code? What is the response text that you get back?

I don’t know much about python, but maybe it has something to do with newline characters in your data hash.

This code works fine:

import requests
url = 'http://192.168.56.2:3000/t/-/1.json'
data = {'api_key': '62bb871486b3bf12af6dde4610e6b2d825588eccd6b0b6ea5de0f35c129992fc','api_username': 'system','title': 'This topic was renamed with python'}
response = requests.put(url, data=data)
print response
print response.text

output:

python app.py
<Response [200]>
{"basic_topic":{"id":1,"title":"This topic was renamed with python","fancy_title":"This topic was renamed with python","slug":"this-topic-was-renamed-with-python","posts_count":1}}

(Valya Barboy) #9

Here’s the response code and text:

<Response [403]>
<!DOCTYPE html>
<html lang="en" class="desktop-view not-mobile-device  ">
  <head>
    <meta charset="utf-8">
    <title>BloomBoard</title>
    <meta name="description" content="BloomBoard Discussions">
    <meta name="discourse_theme_key" content="">
    <meta name="author" content="">
<meta name="generator" content="Discourse 1.9.0.beta4 - https://github.com/discourse/discourse version 24db001bfabea8e76c0738eaca600cbf259aa765">
<link rel="icon" type="image/png" href="/images/default-favicon.ico">
<link rel="apple-touch-icon" type="image/png" href="/images/default-apple-touch-icon.png">
<meta name="theme-color" content="#ffffff">
<meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0, user-scalable=yes">

<script type="application/ld+json">{"@context":"http://schema.org","@type":"WebSite","url":"http://bbhalfdome.trydiscourse.com","potentialAction":{"@type":"SearchAction","target":"http://bbhalfdome.trydiscourse.com/search?q={search_term_string}","query-input":"required name=search_term_string"}}</script>
<link rel="search" type="application/opensearchdescription+xml" href="http://bbhalfdome.trydiscourse.com/opensearch.xml" title="BloomBoard Search">

    <meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="6mPA+8aMYzp9PAWhkGH2mP6bxQVoe+NCB3CbLU+6qq56do0IZ8dGrLAq0I9uVJfusj1/alHOnUkauaPjLFRbQg==" />

      <meta name="fragment" content="!">


    <script>
      window.EmberENV = window.EmberENV || {};
      window.EmberENV['FORCE_JQUERY'] = true;
    </script>

    <link rel='preload' href='https://cdn-standard5.discourse.org/assets/locales/en-c73f715f17c8fbb7c1faf02cb6c8762e0e9c7f68d763fa35d97763e6e71e682f.js' as='script'/>
<script src='https://cdn-standard5.discourse.org/assets/locales/en-c73f715f17c8fbb7c1faf02cb6c8762e0e9c7f68d763fa35d97763e6e71e682f.js'></script>
    <link rel='preload' href='https://cdn-standard5.discourse.org/assets/ember_jquery-a8dcbd325e04410f036f2a791d66d8316c48c5387acdd914de99a5dd6afb3cd3.js' as='script'/>
<script src='https://cdn-standard5.discourse.org/assets/ember_jquery-a8dcbd325e04410f036f2a791d66d8316c48c5387acdd914de99a5dd6afb3cd3.js'></script>
    <link rel='preload' href='https://cdn-standard5.discourse.org/assets/preload-store-ec90ffab9d7a6d9e507dda7cf7343e9d50b8bce624f7f44486ac8fd6b9814309.js' as='script'/>
<script src='https://cdn-standard5.discourse.org/assets/preload-store-ec90ffab9d7a6d9e507dda7cf7343e9d50b8bce624f7f44486ac8fd6b9814309.js'></script>
    <link rel='preload' href='https://cdn-standard5.discourse.org/assets/vendor-199fce5a9e9895329b51b04605f1f5061951acb488baa6b2ea2fc2ae36def529.js' as='script'/>
<script src='https://cdn-standard5.discourse.org/assets/vendor-199fce5a9e9895329b51b04605f1f5061951acb488baa6b2ea2fc2ae36def529.js'></script>
    <link rel='preload' href='https://cdn-standard5.discourse.org/assets/pretty-text-bundle-17f27a2da88b2ef41199101af4fffb397e38bf586aaf3b831d4ec8e7c8ad026f.js' as='script'/>
<script src='https://cdn-standard5.discourse.org/assets/pretty-text-bundle-17f27a2da88b2ef41199101af4fffb397e38bf586aaf3b831d4ec8e7c8ad026f.js'></script>
    <link rel='preload' href='https://cdn-standard5.discourse.org/assets/application-a0c0448850b57452822275328ed709d99db7685836ca04c4d16e9e521f21d133.js' as='script'/>
<script src='https://cdn-standard5.discourse.org/assets/application-a0c0448850b57452822275328ed709d99db7685836ca04c4d16e9e521f21d133.js'></script>
    <link rel='preload' href='https://cdn-standard5.discourse.org/assets/plugin-8f85183a3684e956fd0436f95e9788ee61406202a673831c1b2421f063cfaca5.js' as='script'/>
<script src='https://cdn-standard5.discourse.org/assets/plugin-8f85183a3684e956fd0436f95e9788ee61406202a673831c1b2421f063cfaca5.js'></script>
    <link rel='preload' href='https://cdn-standard5.discourse.org/assets/plugin-third-party-208486774e2283411b48c0ccb54372ce69d914d50de3924f43454ea78caa87c1.js' as='script'/>
<script src='https://cdn-standard5.discourse.org/assets/plugin-third-party-208486774e2283411b48c0ccb54372ce69d914d50de3924f43454ea78caa87c1.js'></script>

      <script src="/extra-locales/admin"></script>
      <link rel='preload' href='https://cdn-standard5.discourse.org/assets/admin-ab19ed38883a7df4bcfcb843d11d9ac52f587fabf4e3d658554bbe2fc56c76dc.js' as='script'/>
<script src='https://cdn-standard5.discourse.org/assets/admin-ab19ed38883a7df4bcfcb843d11d9ac52f587fabf4e3d658554bbe2fc56c76dc.js'></script>

      

    
    <link rel="manifest" href="/manifest.json">


      <link href="https://cdn-standard5.discourse.org/stylesheets/desktop_62362ed5a317985b6be9b3f2484202c9e6fa893f.css?__ws=bbhalfdome.trydiscourse.com" media="all" rel="stylesheet" data-target="desktop"/>

  <link href="https://cdn-standard5.discourse.org/stylesheets/admin_62362ed5a317985b6be9b3f2484202c9e6fa893f.css?__ws=bbhalfdome.trydiscourse.com" media="all" rel="stylesheet" data-target="admin"/>


    

<link rel="preload" href="https://cdn-standard5.discourse.org/assets/fontawesome-webfont-2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe.woff2?http://bbhalfdome.trydiscourse.com&2&v=4.7.0" as="font" type="font/woff2" crossorigin />
<style>
  @font-face {
    font-family: 'FontAwesome';
    src: url('https://cdn-standard5.discourse.org/assets/fontawesome-webfont-2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe.woff2?http://bbhalfdome.trydiscourse.com&2&v=4.7.0') format('woff2'),
         url('https://cdn-standard5.discourse.org/assets/fontawesome-webfont-ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07.woff?http://bbhalfdome.trydiscourse.com&amp;2&v=4.7.0') format('woff');
  }
</style>


    

    
  </head>

  <body class="">
    

    <div class='debug-eyeline'></div>

    <noscript data-path="/t/-/233">
      <header class="d-header">
  <div class="wrap">
    <div class="contents">
      <div class="row">
        <div class="title span13">
          <a href="/">
              <h2 id='site-text-logo'>BloomBoard</h2>
          </a>
        </div>
      </div>
    </div>
  </div>
</header>

      <div id="main-outlet" class="wrap">
        <!-- preload-content: -->
        
<h1 class="page-not-found">Oops! That page doesn’t exist or is private.</h1>

<div class="row page-not-found-topics">
  <div class="span8 popular-topics">
    <h2 class="popular-topics-title">Popular</h2>
      <div class='not-found-topic'>
        <a href="/t/new-topic/107">&quot;NEw_topic&quot;</a>
      </div>
      <div class='not-found-topic'>
        <a href="/t/potions-5/115">Potions 5</a>
      </div>
      <div class='not-found-topic'>
        <a href="/t/potions-3/113">Potions 3</a>
      </div>
      <div class='not-found-topic'>
        <a href="/t/potions-1/111">Potions 1</a>
      </div>
    <br/>
    <a href="/top" class="btn">More&hellip;</a>
  </div>
  <div class="span8 recent-topics">
    <h2 class="recent-topics-title">Recent</h2>
      <div class='not-found-topic'>
        <a href="/t/potions-7/117">Potions 7</a>
      </div>
      <div class='not-found-topic'>
        <a href="/t/potions-6/116">Potions 6</a>
      </div>
      <div class='not-found-topic'>
        <a href="/t/potions-5/115">Potions 5</a>
      </div>
      <div class='not-found-topic'>
        <a href="/t/potions-4/114">Potions 4</a>
      </div>
      <div class='not-found-topic'>
        <a href="/t/potions-3/113">Potions 3</a>
      </div>
      <div class='not-found-topic'>
        <a href="/t/potions-2/112">Potions 2</a>
      </div>
      <div class='not-found-topic'>
        <a href="/t/potions-1/111">Potions 1</a>
      </div>
      <div class='not-found-topic'>
        <a href="/t/title-of-the-new-topic/108">Title of the new topic</a><a class='badge-wrapper  bullet' href='/c/another-bb-high-category'><span class='badge-category-bg' style='background-color: #3AB54A;'></span><span style='color: #FFFFFF;' data-drop-close='true' class='badge-category clear-badge'
                 >Another BB High Category</span></a>
      </div>
      <div class='not-found-topic'>
        <a href="/t/new-topic/107">&quot;NEw_topic&quot;</a>
      </div>
      <div class='not-found-topic'>
        <a href="/t/does-this-work-renamed/88">Does this work? RENAMED</a><a class='badge-wrapper  bullet' href='/c/tn-growth-mindset-spring-2017'><span class='badge-category-bg' style='background-color: #92278F;'></span><span style='color: #FFFFFF;' data-drop-close='true' class='badge-category clear-badge'
                 title='I want to know what a category description looks like in the api. WHOOOOOOO.'>TN Growth Mindset Spring 2017</span></a>
      </div>
    <br/>
    <a href="/latest" class="btn">More&hellip;</a>
  </div>
</div>

  <div class="row">
    <div class="span10 page-not-found-search">
      <h2>Search this site</h2>
      <p>
        <form action='//google.com/search' id='google-search'>
          <input type="text" name="q" value=" ">
          <input type='hidden'name="as_sitesearch" value="http://bbhalfdome.trydiscourse.com">
          <button class="btn btn-primary">Google</button>
        </form>
      </p>
    </div>
  </div>

  <script language="Javascript">
    window.onpopstate = function(event) {
      if (event.state && !window.hasOwnProperty("Discourse")) {  //check if Discourse object exists if not take care of back navigation
        window.location = document.location;
      }
    };
  </script>

        <!-- :preload-content -->
        <footer>
          <nav itemscope itemtype='http://schema.org/SiteNavigationElement'>
            <a href='/'>Home</a>
            <a href="/categories">Categories</a>
            <a href="/guidelines">FAQ/Guidelines</a>
            <a href="/tos">Terms of Service</a>
            <a href="/privacy">Privacy Policy</a>
          </nav>
        </footer>
      </div>

      <footer id='noscript-footer'>
        <p>Powered by <a href="https://www.discourse.org">Discourse</a>, best viewed with JavaScript enabled</p>
      </footer>
    </noscript>

      

    <section id='main'>
    </section>

    <div id='offscreen-content'>
    </div>



    

    <script>
  Ember.RSVP.configure('onerror', function(e) {
    // Ignore TransitionAborted exceptions that bubble up
    if (e && e.message === "TransitionAborted") { return; }

    window.onerror(e && e.message, null,null,null,e);
  });
</script>

<script>

  (function() {
    var ps = require('preload-store').default;

    Discourse.CDN = 'https://cdn-standard5.discourse.org';
    Discourse.BaseUrl = 'bbhalfdome.trydiscourse.com'.replace(/:[\d]*$/,"");
    Discourse.BaseUri = '';
    Discourse.Environment = 'production';
    Discourse.SiteSettings = ps.get('siteSettings');
    Discourse.LetterAvatarVersion = '5_684d5f2aa2461dd37ad36a57b498df43';
    Discourse.MarkdownItURL = 'https://cdn-standard5.discourse.org/assets/markdown-it-bundle-a8d5c9a32112c83bbd9098a3746c1866bf410ef5b397ff63b0b78b0a4ab86737.js';
    I18n.defaultLocale = 'en';
    Discourse.start();
    Discourse.set('assetVersion','ea774097671e27c5e77446bcc7e5e581');
    Discourse.Session.currentProp("disableCustomCSS", false);
    Discourse.HighlightJSPath = "/highlight-js/bbhalfdome.trydiscourse.com/100444ceef8ca161334f64d3ce49fe7a1556f943.js";
  })();
</script>

<link rel='preload' href='https://cdn-standard5.discourse.org/assets/browser-update-f57286e74ddbc53aa899689b01ef467078911e4138050c561939955849af35dd.js' as='script'/>
<script src='https://cdn-standard5.discourse.org/assets/browser-update-f57286e74ddbc53aa899689b01ef467078911e4138050c561939955849af35dd.js'></script>


    

      
    
  </body>
</html>

Python dicts work fine w/ new lines, and I have newlines in my other requests that work. Nevertheless, tried removing them and still get the above.


(Blake Erickson) #10

does topic id 233 even exist on your forum?


(Valya Barboy) #11

Ah. Looks like the ID was saved incorrectly in our DB. Thank you so much, and sorry to bother you.


(Jeff Atwood) #12