Facebook permission to post to my wall

Hi All.

I have finally manged to get login and friends selection etc. to Work with the scrumptious sample app but I cannot post to my wall

I changed code for test purposes from

facebook.request( "me/corona\_scrumptious:eat", "POST", postMsg )  

To :

  facebook.request( "me/feed", "POST", {message = "Hello World"} )  

My app says it posted but i didn’t …

It could very well be a permissions issue because when i check other apps from other devs, i see that they have explicit permission to post on my wall …

How do I achieve this???

  • Add on … when I post to my wall I see http status code: 403 in the console …

Can you post your login code?

oh and your build.settings.

Yes sure, it is simply the scrumptious app sample …

-- -- Project: Facebook Connect scrumptious sample app -- -- Date: March 14, 2013 -- -- Version: 1.0 -- -- File name: mainScreen.lua -- -- Author: Corona Labs -- -- Abstract: Presents the Facebook Connect login dialog, and then posts to the user's stream -- (Also demonstrates the use of external libraries.) -- -- Demonstrates: Facebook library, widget -- -- File dependencies: facebook.lua -- -- Target devices: Simulator and Device (iOS only) -- -- Comments: -- Requires API key and application secret key from Facebook. To begin, log into your Facebook -- account and add the "Developer" application, from which you can create additional apps. -- -- IMPORTANT: Please ensure your app is compatible with Facebook Single Sign-On or your -- Facebook implementation will fail! See the following blog post for more details: -- http://www.coronalabs.com/links/facebook-sso -- -- Sample code is MIT licensed, see http://www.coronalabs.com/links/code/license -- Copyright (C) 2010 Corona Labs Inc. All Rights Reserved. -- --------------------------------------------------------------------------------------- local facebook = require( "facebook" ) local widget = require( "widget" ) local storyboard = require( "storyboard" ) local scene = storyboard.newScene() local function myUnhandledErrorListener( event ) local iHandledTheError = true if iHandledTheError then print( "Handling the unhandled error", event.errorMessage ) else print( "Not handling the unhandled error", event.errorMessage ) end return iHandledTheError end Runtime:addEventListener("unhandledError", myUnhandledErrorListener) function scene:createScene( event ) local group = self.view local appId = "XXXXXXXXXXXX" -- x'ed out on purpse :-) I know the app id must go here :-) local fbCommand = nil local GET\_USER\_INFO = "getInfo" local POST\_MSG = "post" -- Forward references local createList = nil local items = nil local postData = { eating = nil, eatingUrl = nil, place = nil, address = nil, with = {}, } local mealTypes = { { name = "Cheeseburger", url = "http://developer.coronalabs.com/sites/default/files/fbscrumptious/cheeseBurger.html" }, { name = "Pizza", url = "http://developer.coronalabs.com/sites/default/files/fbscrumptious/pizza.html" }, { name = "Hotdog", url = "http://developer.coronalabs.com/sites/default/files/fbscrumptious/hotdog.html" }, { name = "Italian", url = "http://developer.coronalabs.com/sites/default/files/fbscrumptious/italian.html" }, { name = "French", url = "http://developer.coronalabs.com/sites/default/files/fbscrumptious/french.html" }, { name = "Chinese", url = "http://developer.coronalabs.com/sites/default/files/fbscrumptious/chinese.html" }, { name = "Thai", url = "http://developer.coronalabs.com/sites/default/files/fbscrumptious/thai.html" }, { name = "Indian", url = "http://developer.coronalabs.com/sites/default/files/fbscrumptious/indian.html" }, } local background = display.newRect( 0, 0, display.contentWidth, display.contentHeight ) background.x = display.contentCenterX background.y = display.contentCenterY + display.statusBarHeight background:setFillColor( 255, 255, 255 ) group:insert( background ) -- Settings local function showSettings( event ) -- Hide the settings button transition.to( event.target, { alpha = 0 } ) -- Show the scruptious button & reset it's position on the navbar if storyboard.scrumptiousButton then storyboard.scrumptiousButton.alpha = 1 -- Reset the position storyboard.scrumptiousButton.x = storyboard.scrumptiousButton.contentWidth \* 0.5 end -- Hide the navbar text storyboard.navBarText.isVisible = false -- Goto the logout screen storyboard.gotoScene( "logoutScreen", "slideLeft" ) end -- Settings button storyboard.settingsButton = widget.newButton { width = 60, height = 30, defaultFile = "assets/default.png", overFile = "assets/over.png", label = "Settings", labelColor = { default = { 255, 255, 255 }, over = { 255, 255, 255, 128 }, }, fontSize = 12, onRelease = showSettings, } storyboard.settingsButton.x = display.contentWidth - 32 storyboard.settingsButton.y = storyboard.navBar.y storyboard.navBarGroup:insert( storyboard.settingsButton ) -- Profile Pic local userPicture = display.newImageRect( storyboard.userData.firstName .. storyboard.userData.lastName .. storyboard.userData.id .. ".png", system.TemporaryDirectory, 80, 80 ) userPicture.x = 20 + userPicture.contentWidth \* 0.5 userPicture.y = 120 group:insert( userPicture ) -- User name local userName = display.newText( storyboard.userData.firstName .. " " .. storyboard.userData.lastName, 0, 0, native.systemFont, 16 ) userName.x = userPicture.x + userPicture.contentWidth \* 0.5 + userName.contentWidth \* 0.5 + 10 userName.y = userPicture.y - userPicture.contentHeight \* 0.5 + userName.contentHeight \* 0.5 userName:setTextColor( 0 ) group:insert( userName ) -- Function to execute on completion of friend choice local function onCompleteFriends( event ) local friendsSelected = {} -- If there is event.data print it's key/value pairs if event.data then print( "event.data: {" ); if "table" == type( event.data ) then for i = 1, #event.data do print( "{" ) for k, v in pairs( event.data[i] ) do print( k, ":", v ) -- Add friend to post data if "id" == k then postData.with[#postData.with + 1] = v elseif "fullName" == k then friendsSelected[#friendsSelected + 1] = v end end print( "picture : {" ) for k, v in pairs( event.data[i].picture.data ) do print( k, ":", v ) end print( "}," ) print( "}," ) end end -- Set the with friends string to the first selected friend by default local withString = friendsSelected[1] -- If there is more than one friend selected, append the id string if #postData.with \> 1 then for i = 2, #postData.with do -- postData.with = postData[i-1].with .. "," .. postData[i].with end end -- If there is more than one friend selected, append the string if #friendsSelected \> 1 then withString = friendsSelected[1] .. " and " .. #friendsSelected - 1 .. " others" end -- Set the description items[3].description = withString -- Recreate the list createList() print( "}" ); end end local function onCompletePlaces( event ) if event.data then print( "{" ) for k, v in pairs( event.data ) do print( k, ":", v ) -- Add place to post data if "name" == k then postData.place = v -- Update the description items[2].description = postData.place -- Recreate the list createList() end -- Add place address to post data if "street" == k then postData.address = v elseif "id" == k then postData.id = v elseif "state" == k or "city" == k then if string.len( v ) \> 0 then postData.address = postData.address .. ", " .. v end end if "picture" == k then print( "picture : {" ) for k, v in pairs( v.data ) do print( k, ":", v ) end print( "}," ) end end print( "}" ) end end local function facebookListener( event ) if "request" == event.type then native.showAlert( "Result", "Message succesfully posted!", { "Ok" } ) -- Reset the item descriptions items[1].description = "Select one" items[2].description = "Select one" items[3].description = "Select friends" -- Recreate the list createList() -- After a successful login event, send the FB command -- Note: If the app is already logged in, we will still get a "login" phase elseif "session" == event.type then -- event.phase is one of: "login", "loginFailed", "loginCancelled", "logout" if event.phase ~= "login" then -- Exit if login error return end -- This code posts a message to your Facebook Wall if fbCommand == POST\_MSG then local includePlace = false local includeWith = false -- Handle errors if type( postData.place ) == "string" and string.len( postData.place ) \> 0 then includePlace = true end if #postData.with \> 0 then includeWith = true end -- Disabled the validation to allow post button to work for simple string post .... --if type( postData.eating ) ~= "string" then -- native.showAlert( "Missing selection", "You need to select what food you are eating", { "OK" } ) -- return --end -- If all is ok, post the message to the users wall local friends = "" -- Set the with friends string accordingly if #postData.with \> 0 then for i = 1, #postData.with do if i \<= 1 then friends = postData.with[i] elseif i \>= #postData.with then friends = friends .. "," .. postData.with[i] else friends = friends .. "," .. postData.with[i] end end end -- Message to post to the users wall local messageToPost = storyboard.userData.firstName .. " " .. storyboard.userData.lastName local placeToPost = "" local selectedMeal = postData.eatingUrl if includePlace then placeToPost = postData.id end -- Set the message local postMsg = {} -- Set up the post message if "string" == type( selectedMeal ) and string.len( selectedMeal ) \> 1 then postMsg.meal = selectedMeal end -- Set the friends we selected to be tagged in our timeline post if "string" == type( friends ) and string.len( friends ) \> 1 then postMsg.tags = friends end if "string" == type( placeToPost ) and string.len( placeToPost ) \> 1 then postMsg.place = placeToPost end -- Post the message -- Tried all of the following : -- facebook.request( "me/corona\_scrumptious:eat", "POST", postMsg ) --facebook.request( "me/feed", "POST", postMsg ) facebook.request( "me/feed", "POST", postMsg ) end return true end end -- Pick place local function pickPlace( event ) facebook.showDialog( "place", { title = "Select A Restaurant", longitude = 48.857875, latitude = 2.294635, searchText = "restaurant", resultsLimit = 20, radiusInMeters = 2000 }, onCompletePlaces ) end -- Show friends local function pickFriends( event ) facebook.showDialog( "friends", onCompleteFriends ) end -- Pick meal local function pickMeal( event ) actionSheet:show() end -- Setup the items table items = { { image = "assets/action-eating.png", title = "What are you eating?", description = "Select one", onTouch = pickMeal }, { image = "assets/action-location.png", title = "Where are you?", description = "Select one", onTouch = pickPlace }, { image = "assets/action-people.png", title = "With whom?", description = "Select friends", onTouch = pickFriends }, } local function onRowTouch( event ) local phase = event.phase local row = event.target if "release" == phase then row.\_touchFunction() end return true end local function onRowRender( event ) local row = event.row -- The row's image row.image = display.newImageRect( items[row.index].image, 34, 34 ) row.image.x = row.image.contentWidth \* 0.5 row.image.y = row.contentHeight \* 0.5 row:insert( row.image ) -- The row's title row.title = display.newText( items[row.index].title, 0, 0, native.systemFont, 18 ) row.title.x = row.image.x + row.image.contentWidth \* 0.5 + row.title.contentWidth \* 0.5 + 8 row.title.y = row.contentHeight \* 0.5 - row.title.contentHeight \* 0.5 + 4 row.title:setTextColor( 0 ) row:insert( row.title ) -- The row's description row.description = display.newText( items[row.index].description, 0, 0, native.systemFont, 14 ) row.description.x = row.image.x + row.image.contentWidth \* 0.5 + row.description.contentWidth \* 0.5 + 8 row.description.y = row.contentHeight \* 0.5 + row.description.contentHeight \* 0.5 row.description:setTextColor( 100, 139, 237 ) row:insert( row.description ) -- Set the rows touch function row.\_touchFunction = items[row.index].onTouch end -- Function to create a tableView list createList = function() if list then list:deleteAllRows() display.remove( list ) list = nil end -- Create a list list = widget.newTableView { left = 10, top = 200, width = display.contentWidth - 20, height = 100, hideBackground = true, isLocked = true, onRowRender = onRowRender, onRowTouch = onRowTouch, } group:insert( list ) for i = 1, #items do list:insertRow { id = items[i], rowColor = { default = { 255, 255, 255, 255 }, }, } end end -- Create the list createList() -- Announce! local function postMessage( event ) fbCommand = POST\_MSG -- Tried both actions and stream ... It seems to give http 403 in both cases... --facebook.login( appId, facebookListener, { "publish\_actions" } ) facebook.login( appId, facebookListener, { "publish\_stream" } ) end -- Announce button local announceButton = widget.newButton { width = 180, height = 59, label = "Announce!", onRelease = postMessage, } announceButton.x = display.contentCenterX announceButton.y = display.contentHeight - 80 group:insert( announceButton ) -- Create an action sheet local function createActionSheet( rows ) local group = display.newGroup() local underlay = display.newRect( group, 0, 0, display.contentWidth, display.contentHeight ) underlay:setFillColor( 0, 0, 0, 128 ) underlay:addEventListener( "touch", function() return true end ) local title = display.newEmbossedText( group, "Select a meal", 0, 0, native.systemFont, 14 ) title:setTextColor( 255 ) title.x = display.contentCenterX title.y = storyboard.navBar.y local function onRowRender( event ) local row = event.row local rowTitle = display.newText( rows[row.index].name, 0, 0, native.systemFontBold, 24 ) rowTitle.x = row.contentWidth \* 0.5 rowTitle.y = row.contentHeight \* 0.5 rowTitle:setTextColor( 0 ) row:insert( rowTitle ) end local function onRowTouch( event ) local phase = event.phase local row = event.target if "release" == phase then postData.eating = rows[row.index].name postData.eatingUrl = rows[row.index].url actionSheet:hide() end return true end -- Create a tableView local tableView = widget.newTableView { left = 20, top = display.statusBarHeight + 64, width = display.contentWidth - 40, height = 300, maskFile = "assets/actionSheetMask.png", onRowRender = onRowRender, onRowTouch = onRowTouch, } tableView.maskY = 310 \* 0.5 group:insert( tableView ) -- Create the rows for i = 1, #rows do tableView:insertRow { id = rows[i], rowHeight = 50, } end -- Apply a gradient on top of the tableView local tableViewGradient = graphics.newGradient( { 252, 252, 252 }, { 141, 141, 141 }, "down" ) local gradientRect = display.newRect( 20, display.statusBarHeight + 64, display.contentWidth - 40, 310 ) gradientRect:setFillColor( tableViewGradient ) gradientRect.alpha = 0.25 group:insert( gradientRect ) local underlayBorder = display.newImageRect( group, "assets/actionSheetBorder.png", 300, 330 ) underlayBorder.x = gradientRect.x + 1 underlayBorder.y = gradientRect.y underlayBorder:toBack() local function hideActionSheet( event ) transition.to( group, { y = display.contentHeight + group.contentHeight \* 0.5, transition = easing.inOutExpo } ) transition.to( storyboard.navBarText, { alpha = 1 } ) transition.to( storyboard.settingsButton, { alpha = 1 } ) end local cancelButton = widget.newButton { width = 298, height = 56, label = "Cancel", onRelease = hideActionSheet, } cancelButton.x = display.contentCenterX cancelButton.y = display.contentHeight - cancelButton.contentHeight \* 0.5 - 10 group:insert( cancelButton ) -- Show the actionSheet function group:show() -- Show the group transition.to( self, { y = 0, transition = easing.inOutExpo } ) -- Hide the navbar text transition.to( storyboard.navBarText, { alpha = 0 } ) -- Hide the settings button transition.to( storyboard.settingsButton, { alpha = 0 } ) end -- Hide the actionSheet function group:hide() local function onComplete( event ) items[1].description = postData.eating createList() end -- Hide the group transition.to( self, { y = display.contentHeight + self.contentHeight \* 0.5, transition = easing.inOutExpo, onComplete = onComplete } ) -- Show the navbar text transition.to( storyboard.navBarText, { alpha = 1 } ) -- Show the settings button transition.to( storyboard.settingsButton, { alpha = 1 } ) end group.y = display.contentHeight return group end -- Create the actionsheet actionSheet = createActionSheet( mealTypes ) end scene:addEventListener( "createScene", event ) return scene

Now … You might argue that this not my login code :slight_smile:

I just took a look at the code for the login button …

 local function loginUser( event ) event.target.isVisible = false spinner.isVisible = true spinner:start() -- call the login method of the FB session object, passing in a handler -- to be called upon successful login. fbCommand = GET\_USER\_INFO facebook.login( appId, facebookListener ) end

changeing

 
 

&nbsp;facebook.login( appId, facebookListener ) &nbsp;

to

 

facebook.login( appId, facebookListener , { "publish\_actions" } ) &nbsp;

had some effect … Now I get http error 400 instead of 403 … Maybe this hints you to what is wrong?
 

Can you post more of your error log around this 403 error.

Are you sure your keyhash is setup correctly?

Is your appID correct?

Can you try the regular facebook sample app (not the scrumptilcious one)?  Make sure to set your Facebook AppID in the build.settings and in the main.lua correctly.

Hi Rob.

I really cannot explain what is going on :frowning:

I just now wanted to collect some info for you and I pressed announce button Again and now it Works …

hmmmmmm … This is really strange.

Did not change anything since I change the initial login code

facebook.login( appId, facebookListener ) &nbsp;

to

&nbsp; facebook.login( appId, facebookListener , { "publish\_actions" } ) &nbsp;

So … just tested it out once Again …

It seems the solution in Scrumptious was to add publish_actions to the initial login …

This is in fact understandable, but still i do not get why this is not then done in the sample?

I guess I am not the only one who have tried this sample …

What is wrong ? Why ? Who ? :smiley:

  • Add on … when I post to my wall I see http status code: 403 in the console …

Can you post your login code?

oh and your build.settings.

Yes sure, it is simply the scrumptious app sample …

-- -- Project: Facebook Connect scrumptious sample app -- -- Date: March 14, 2013 -- -- Version: 1.0 -- -- File name: mainScreen.lua -- -- Author: Corona Labs -- -- Abstract: Presents the Facebook Connect login dialog, and then posts to the user's stream -- (Also demonstrates the use of external libraries.) -- -- Demonstrates: Facebook library, widget -- -- File dependencies: facebook.lua -- -- Target devices: Simulator and Device (iOS only) -- -- Comments: -- Requires API key and application secret key from Facebook. To begin, log into your Facebook -- account and add the "Developer" application, from which you can create additional apps. -- -- IMPORTANT: Please ensure your app is compatible with Facebook Single Sign-On or your -- Facebook implementation will fail! See the following blog post for more details: -- http://www.coronalabs.com/links/facebook-sso -- -- Sample code is MIT licensed, see http://www.coronalabs.com/links/code/license -- Copyright (C) 2010 Corona Labs Inc. All Rights Reserved. -- --------------------------------------------------------------------------------------- local facebook = require( "facebook" ) local widget = require( "widget" ) local storyboard = require( "storyboard" ) local scene = storyboard.newScene() local function myUnhandledErrorListener( event ) local iHandledTheError = true if iHandledTheError then print( "Handling the unhandled error", event.errorMessage ) else print( "Not handling the unhandled error", event.errorMessage ) end return iHandledTheError end Runtime:addEventListener("unhandledError", myUnhandledErrorListener) function scene:createScene( event ) local group = self.view local appId = "XXXXXXXXXXXX" -- x'ed out on purpse :-) I know the app id must go here :-) local fbCommand = nil local GET\_USER\_INFO = "getInfo" local POST\_MSG = "post" -- Forward references local createList = nil local items = nil local postData = { eating = nil, eatingUrl = nil, place = nil, address = nil, with = {}, } local mealTypes = { { name = "Cheeseburger", url = "http://developer.coronalabs.com/sites/default/files/fbscrumptious/cheeseBurger.html" }, { name = "Pizza", url = "http://developer.coronalabs.com/sites/default/files/fbscrumptious/pizza.html" }, { name = "Hotdog", url = "http://developer.coronalabs.com/sites/default/files/fbscrumptious/hotdog.html" }, { name = "Italian", url = "http://developer.coronalabs.com/sites/default/files/fbscrumptious/italian.html" }, { name = "French", url = "http://developer.coronalabs.com/sites/default/files/fbscrumptious/french.html" }, { name = "Chinese", url = "http://developer.coronalabs.com/sites/default/files/fbscrumptious/chinese.html" }, { name = "Thai", url = "http://developer.coronalabs.com/sites/default/files/fbscrumptious/thai.html" }, { name = "Indian", url = "http://developer.coronalabs.com/sites/default/files/fbscrumptious/indian.html" }, } local background = display.newRect( 0, 0, display.contentWidth, display.contentHeight ) background.x = display.contentCenterX background.y = display.contentCenterY + display.statusBarHeight background:setFillColor( 255, 255, 255 ) group:insert( background ) -- Settings local function showSettings( event ) -- Hide the settings button transition.to( event.target, { alpha = 0 } ) -- Show the scruptious button & reset it's position on the navbar if storyboard.scrumptiousButton then storyboard.scrumptiousButton.alpha = 1 -- Reset the position storyboard.scrumptiousButton.x = storyboard.scrumptiousButton.contentWidth \* 0.5 end -- Hide the navbar text storyboard.navBarText.isVisible = false -- Goto the logout screen storyboard.gotoScene( "logoutScreen", "slideLeft" ) end -- Settings button storyboard.settingsButton = widget.newButton { width = 60, height = 30, defaultFile = "assets/default.png", overFile = "assets/over.png", label = "Settings", labelColor = { default = { 255, 255, 255 }, over = { 255, 255, 255, 128 }, }, fontSize = 12, onRelease = showSettings, } storyboard.settingsButton.x = display.contentWidth - 32 storyboard.settingsButton.y = storyboard.navBar.y storyboard.navBarGroup:insert( storyboard.settingsButton ) -- Profile Pic local userPicture = display.newImageRect( storyboard.userData.firstName .. storyboard.userData.lastName .. storyboard.userData.id .. ".png", system.TemporaryDirectory, 80, 80 ) userPicture.x = 20 + userPicture.contentWidth \* 0.5 userPicture.y = 120 group:insert( userPicture ) -- User name local userName = display.newText( storyboard.userData.firstName .. " " .. storyboard.userData.lastName, 0, 0, native.systemFont, 16 ) userName.x = userPicture.x + userPicture.contentWidth \* 0.5 + userName.contentWidth \* 0.5 + 10 userName.y = userPicture.y - userPicture.contentHeight \* 0.5 + userName.contentHeight \* 0.5 userName:setTextColor( 0 ) group:insert( userName ) -- Function to execute on completion of friend choice local function onCompleteFriends( event ) local friendsSelected = {} -- If there is event.data print it's key/value pairs if event.data then print( "event.data: {" ); if "table" == type( event.data ) then for i = 1, #event.data do print( "{" ) for k, v in pairs( event.data[i] ) do print( k, ":", v ) -- Add friend to post data if "id" == k then postData.with[#postData.with + 1] = v elseif "fullName" == k then friendsSelected[#friendsSelected + 1] = v end end print( "picture : {" ) for k, v in pairs( event.data[i].picture.data ) do print( k, ":", v ) end print( "}," ) print( "}," ) end end -- Set the with friends string to the first selected friend by default local withString = friendsSelected[1] -- If there is more than one friend selected, append the id string if #postData.with \> 1 then for i = 2, #postData.with do -- postData.with = postData[i-1].with .. "," .. postData[i].with end end -- If there is more than one friend selected, append the string if #friendsSelected \> 1 then withString = friendsSelected[1] .. " and " .. #friendsSelected - 1 .. " others" end -- Set the description items[3].description = withString -- Recreate the list createList() print( "}" ); end end local function onCompletePlaces( event ) if event.data then print( "{" ) for k, v in pairs( event.data ) do print( k, ":", v ) -- Add place to post data if "name" == k then postData.place = v -- Update the description items[2].description = postData.place -- Recreate the list createList() end -- Add place address to post data if "street" == k then postData.address = v elseif "id" == k then postData.id = v elseif "state" == k or "city" == k then if string.len( v ) \> 0 then postData.address = postData.address .. ", " .. v end end if "picture" == k then print( "picture : {" ) for k, v in pairs( v.data ) do print( k, ":", v ) end print( "}," ) end end print( "}" ) end end local function facebookListener( event ) if "request" == event.type then native.showAlert( "Result", "Message succesfully posted!", { "Ok" } ) -- Reset the item descriptions items[1].description = "Select one" items[2].description = "Select one" items[3].description = "Select friends" -- Recreate the list createList() -- After a successful login event, send the FB command -- Note: If the app is already logged in, we will still get a "login" phase elseif "session" == event.type then -- event.phase is one of: "login", "loginFailed", "loginCancelled", "logout" if event.phase ~= "login" then -- Exit if login error return end -- This code posts a message to your Facebook Wall if fbCommand == POST\_MSG then local includePlace = false local includeWith = false -- Handle errors if type( postData.place ) == "string" and string.len( postData.place ) \> 0 then includePlace = true end if #postData.with \> 0 then includeWith = true end -- Disabled the validation to allow post button to work for simple string post .... --if type( postData.eating ) ~= "string" then -- native.showAlert( "Missing selection", "You need to select what food you are eating", { "OK" } ) -- return --end -- If all is ok, post the message to the users wall local friends = "" -- Set the with friends string accordingly if #postData.with \> 0 then for i = 1, #postData.with do if i \<= 1 then friends = postData.with[i] elseif i \>= #postData.with then friends = friends .. "," .. postData.with[i] else friends = friends .. "," .. postData.with[i] end end end -- Message to post to the users wall local messageToPost = storyboard.userData.firstName .. " " .. storyboard.userData.lastName local placeToPost = "" local selectedMeal = postData.eatingUrl if includePlace then placeToPost = postData.id end -- Set the message local postMsg = {} -- Set up the post message if "string" == type( selectedMeal ) and string.len( selectedMeal ) \> 1 then postMsg.meal = selectedMeal end -- Set the friends we selected to be tagged in our timeline post if "string" == type( friends ) and string.len( friends ) \> 1 then postMsg.tags = friends end if "string" == type( placeToPost ) and string.len( placeToPost ) \> 1 then postMsg.place = placeToPost end -- Post the message -- Tried all of the following : -- facebook.request( "me/corona\_scrumptious:eat", "POST", postMsg ) --facebook.request( "me/feed", "POST", postMsg ) facebook.request( "me/feed", "POST", postMsg ) end return true end end -- Pick place local function pickPlace( event ) facebook.showDialog( "place", { title = "Select A Restaurant", longitude = 48.857875, latitude = 2.294635, searchText = "restaurant", resultsLimit = 20, radiusInMeters = 2000 }, onCompletePlaces ) end -- Show friends local function pickFriends( event ) facebook.showDialog( "friends", onCompleteFriends ) end -- Pick meal local function pickMeal( event ) actionSheet:show() end -- Setup the items table items = { { image = "assets/action-eating.png", title = "What are you eating?", description = "Select one", onTouch = pickMeal }, { image = "assets/action-location.png", title = "Where are you?", description = "Select one", onTouch = pickPlace }, { image = "assets/action-people.png", title = "With whom?", description = "Select friends", onTouch = pickFriends }, } local function onRowTouch( event ) local phase = event.phase local row = event.target if "release" == phase then row.\_touchFunction() end return true end local function onRowRender( event ) local row = event.row -- The row's image row.image = display.newImageRect( items[row.index].image, 34, 34 ) row.image.x = row.image.contentWidth \* 0.5 row.image.y = row.contentHeight \* 0.5 row:insert( row.image ) -- The row's title row.title = display.newText( items[row.index].title, 0, 0, native.systemFont, 18 ) row.title.x = row.image.x + row.image.contentWidth \* 0.5 + row.title.contentWidth \* 0.5 + 8 row.title.y = row.contentHeight \* 0.5 - row.title.contentHeight \* 0.5 + 4 row.title:setTextColor( 0 ) row:insert( row.title ) -- The row's description row.description = display.newText( items[row.index].description, 0, 0, native.systemFont, 14 ) row.description.x = row.image.x + row.image.contentWidth \* 0.5 + row.description.contentWidth \* 0.5 + 8 row.description.y = row.contentHeight \* 0.5 + row.description.contentHeight \* 0.5 row.description:setTextColor( 100, 139, 237 ) row:insert( row.description ) -- Set the rows touch function row.\_touchFunction = items[row.index].onTouch end -- Function to create a tableView list createList = function() if list then list:deleteAllRows() display.remove( list ) list = nil end -- Create a list list = widget.newTableView { left = 10, top = 200, width = display.contentWidth - 20, height = 100, hideBackground = true, isLocked = true, onRowRender = onRowRender, onRowTouch = onRowTouch, } group:insert( list ) for i = 1, #items do list:insertRow { id = items[i], rowColor = { default = { 255, 255, 255, 255 }, }, } end end -- Create the list createList() -- Announce! local function postMessage( event ) fbCommand = POST\_MSG -- Tried both actions and stream ... It seems to give http 403 in both cases... --facebook.login( appId, facebookListener, { "publish\_actions" } ) facebook.login( appId, facebookListener, { "publish\_stream" } ) end -- Announce button local announceButton = widget.newButton { width = 180, height = 59, label = "Announce!", onRelease = postMessage, } announceButton.x = display.contentCenterX announceButton.y = display.contentHeight - 80 group:insert( announceButton ) -- Create an action sheet local function createActionSheet( rows ) local group = display.newGroup() local underlay = display.newRect( group, 0, 0, display.contentWidth, display.contentHeight ) underlay:setFillColor( 0, 0, 0, 128 ) underlay:addEventListener( "touch", function() return true end ) local title = display.newEmbossedText( group, "Select a meal", 0, 0, native.systemFont, 14 ) title:setTextColor( 255 ) title.x = display.contentCenterX title.y = storyboard.navBar.y local function onRowRender( event ) local row = event.row local rowTitle = display.newText( rows[row.index].name, 0, 0, native.systemFontBold, 24 ) rowTitle.x = row.contentWidth \* 0.5 rowTitle.y = row.contentHeight \* 0.5 rowTitle:setTextColor( 0 ) row:insert( rowTitle ) end local function onRowTouch( event ) local phase = event.phase local row = event.target if "release" == phase then postData.eating = rows[row.index].name postData.eatingUrl = rows[row.index].url actionSheet:hide() end return true end -- Create a tableView local tableView = widget.newTableView { left = 20, top = display.statusBarHeight + 64, width = display.contentWidth - 40, height = 300, maskFile = "assets/actionSheetMask.png", onRowRender = onRowRender, onRowTouch = onRowTouch, } tableView.maskY = 310 \* 0.5 group:insert( tableView ) -- Create the rows for i = 1, #rows do tableView:insertRow { id = rows[i], rowHeight = 50, } end -- Apply a gradient on top of the tableView local tableViewGradient = graphics.newGradient( { 252, 252, 252 }, { 141, 141, 141 }, "down" ) local gradientRect = display.newRect( 20, display.statusBarHeight + 64, display.contentWidth - 40, 310 ) gradientRect:setFillColor( tableViewGradient ) gradientRect.alpha = 0.25 group:insert( gradientRect ) local underlayBorder = display.newImageRect( group, "assets/actionSheetBorder.png", 300, 330 ) underlayBorder.x = gradientRect.x + 1 underlayBorder.y = gradientRect.y underlayBorder:toBack() local function hideActionSheet( event ) transition.to( group, { y = display.contentHeight + group.contentHeight \* 0.5, transition = easing.inOutExpo } ) transition.to( storyboard.navBarText, { alpha = 1 } ) transition.to( storyboard.settingsButton, { alpha = 1 } ) end local cancelButton = widget.newButton { width = 298, height = 56, label = "Cancel", onRelease = hideActionSheet, } cancelButton.x = display.contentCenterX cancelButton.y = display.contentHeight - cancelButton.contentHeight \* 0.5 - 10 group:insert( cancelButton ) -- Show the actionSheet function group:show() -- Show the group transition.to( self, { y = 0, transition = easing.inOutExpo } ) -- Hide the navbar text transition.to( storyboard.navBarText, { alpha = 0 } ) -- Hide the settings button transition.to( storyboard.settingsButton, { alpha = 0 } ) end -- Hide the actionSheet function group:hide() local function onComplete( event ) items[1].description = postData.eating createList() end -- Hide the group transition.to( self, { y = display.contentHeight + self.contentHeight \* 0.5, transition = easing.inOutExpo, onComplete = onComplete } ) -- Show the navbar text transition.to( storyboard.navBarText, { alpha = 1 } ) -- Show the settings button transition.to( storyboard.settingsButton, { alpha = 1 } ) end group.y = display.contentHeight return group end -- Create the actionsheet actionSheet = createActionSheet( mealTypes ) end scene:addEventListener( "createScene", event ) return scene

Now … You might argue that this not my login code :slight_smile:

I just took a look at the code for the login button …

 local function loginUser( event ) event.target.isVisible = false spinner.isVisible = true spinner:start() -- call the login method of the FB session object, passing in a handler -- to be called upon successful login. fbCommand = GET\_USER\_INFO facebook.login( appId, facebookListener ) end

changeing

 
 

&nbsp;facebook.login( appId, facebookListener ) &nbsp;

to

 

facebook.login( appId, facebookListener , { "publish\_actions" } ) &nbsp;

had some effect … Now I get http error 400 instead of 403 … Maybe this hints you to what is wrong?
 

Can you post more of your error log around this 403 error.

Are you sure your keyhash is setup correctly?

Is your appID correct?

Can you try the regular facebook sample app (not the scrumptilcious one)?  Make sure to set your Facebook AppID in the build.settings and in the main.lua correctly.

Hi Rob.

I really cannot explain what is going on :frowning:

I just now wanted to collect some info for you and I pressed announce button Again and now it Works …

hmmmmmm … This is really strange.

Did not change anything since I change the initial login code

facebook.login( appId, facebookListener ) &nbsp;

to

&nbsp; facebook.login( appId, facebookListener , { "publish\_actions" } ) &nbsp;

So … just tested it out once Again …

It seems the solution in Scrumptious was to add publish_actions to the initial login …

This is in fact understandable, but still i do not get why this is not then done in the sample?

I guess I am not the only one who have tried this sample …

What is wrong ? Why ? Who ? :smiley: