This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
DannySMc's profile picture

Social Net API (CC's own social network)

Started by DannySMc, 20 March 2015 - 08:59 AM
DannySMc #1
Posted 20 March 2015 - 09:59 AM
Hey guys,

License:
I don't care too much, just add credits to me in the forum post and the actual program for the API. That's all I ask.
This code is all mine other than the code I supply to allow you to install on-the-fly.

I wrote a post a little while ago, and after the amount of positive comments, I implemented the API. Please use this for good, and I hope you like it:) It does work, but I am still adding to the php script so if it errors one time and not again, this may be me playing with the PHP scripts.

The API can be downloaded or you can use the code I shall supply to download and install it on the fly. This is thanks to: (Geforce Fan) for the original source code and has been modified to work with just my API :D/>.

Errors go to my github repo (below) and then submit an issue. If you wish to get the code then:

If you wish to download the code then please go to my github repo or alternatively you can use the on-the-fly method and download it and run it on boot? :D/>

NOTE:
Please don't hate as it is an alpha version and it is my first release of the code, I do know oeed is planning to make a client but of course I would love to have more than one client out there, so people can choose from. Also when you make a client it will go on my app store.

How the chat works:
As you know I implemented a chat system which has a global, group and personal messenger, if you wish to make it asynchronous then please look here. The PHP script will keep your messages down to 25/26 messages stored, so that is the latest history, of course you can make your own history and make it local like caching, but to make it asynchronous then it needs to be small. This will count for all chats. Global is for everyone so remember anyone can talk. Group can make a group chat that you and your friends can talk in, make it different so people can't guess the group if you are talking about projects etc. The personal messenger is just like a user to user messaging system.

Here is the code to run the API on the fly:
Spoiler

function loadapi()
	if fs.exists("snet") then
	os.loadAPI("snet")
		return true
	end
	aa = aa or {}
	local a = http.get("https://vault.dannysmc.com/lua/api/socialnetapi.lua")
	a = a.readAll()
	local env = {}
	a = loadstring(a)
	local env = getfenv()
	setfenv(a,env)
	local status, err = pcall(a, unpack(aa))
	if (not status) and err then
		printError("Error loading api")
		return false
	end
	local returned = err
	env = env
	_G["snet"] = env
end
loadapi()

If a request comes back with an error (posting data and user login/register) have an error code which is already formatted on the way back so use a code like:

local req = user.login(username, password)
req = req.readAll()
if req == "true" then
	-- Do the code if they exist
else
	print(req)
	-- prints the error message
end

Anyway the api is simple and pretty easy to use, here is the documentation I wrote (which is a huge comment in the actual API) when making the API:
Error codes are at the bottom!


Glossary:
+ MDA: Multi-Dimensional Array


All functions will require a username and a password, this is to check they exist, on every function. If I was you I would store it in a username and password variable, so the user (or you) do not have to keep adding it.


->
user.login(username, password)
This will attempt to log a user in, by checking their username and password against the user database, if they exist, it will return true, otherwise it will return with the error.

->
user.register(username, password, email)
This will register a new user by sending up the username, password and email. If it worked then it will return true, if it didn't it will turn the reason why, either an error occured or the username was already taken.

->
user.list(username, password)
This will list all users that are registered, this will ONLY, list the username and this is a normal array. If you still are confused please look at the multidimensional arrays heading which will explain how to handle normal and multi-dimensional arrays.

->
store.appsall()
This will get a list of all apps that are stored in the database that are public. It will return as a multidimesional array, you will have to readAll() then unserialize to be able to index it with ComputerCraft. Examples of multidimensional arrays and how to index them are found at further down.

->
store.appsuser()
This will return a multidimensional array of all apps that have been made by the user you passed as an argument.

->
social.post.new(username, password, header, message)
This will let you post a status, you will add a header and a message, so a header would be say the subject of the status, and the message will be the main body content. If you wish to use a small post then you can optionally use tweet, which will send up a small sized status. The character limit on a new post is 4096 characters.

->
social.post.tweet(username, password, message)
Same as a new post, the differences being that it will only allow accept 255 characters and doesn't support any type of subjects/headers.

->
social.post.getall(username, password)
This will get all posts that are on the system, this is any user and all posts. Please note if you do use a friends list then please the scripter of the program will need to set this as I am not keen on the idea of having friends list because not may people will use the API. So for now I guess you can use the friends sub-functions to allow you to display content that your friends have posted.

->
social.post.getuser(username, password, usertoget)
This will get all posts that a user has posted and return it as a MDA. This is good to use for viewing a users profile.

->
social.post.delete(username, password, postid)
This will delete a post that is owned by you, please note that you will need to get the id of the post/tweet, this will be the first value in the MDA.

->
social.profile.edit(username, password, fullname, age, bio, forumsusername)
This will of course allow you to edit your profile, please note that the only things that can be saved are username, fullname, age, bio and forums username. These are optional and don't have to be added.

->
social.profile.get(username, password, usertoget)
This will get a users profile as a MDA, these can be used in templates you create.

->
social.friends.add(username, password, frienduser)
This is for anyone that wishes to use a friends list, this allows you to add a username to your friends list.

->
social.friends.get(username, password, usertoget)
This will grab a users followers/friends list.

->
social.chat_global.new(username, password, message)
This will use the global chat which is a huge chat that will allow everyone to talk together, kind of like IRC. This will take a message and then will be added please remember when you add a message make sure to download the chat again, this can be of course automatically updated every few seconds but this WILL CAUSE DELAYS.

->
social.chat_global.get(username, password)
This will grab the global chat. Please note messages will slowly get longer and longer therefore the chat may become slower and slower to download.

->
social.chat_group.new(username, password, groupname, message)
This is a group chat allowing a set of users to chat in a group. You can define a groupname and then chat in it with whoever you want, please note that groups can be accessed by anyone, so always make sure to name chats very differently, even maybe use a hash as a groupname.

->
social.chat_group.get(username, password, groupname)
This will download the current chat of the group you choose, by giving it a groupname argument this will allow you to chat in that group.

->
social.chat_pm.new(username, password, recipient, message)
This is a personal messenger and works the same as all others but instead you give it a recipient instead of a groupname and then this will add a new message to that user.

->
social.chat_pm.get(username, password, recipient)
You will only be able to see a chat from your their username, if you want you would have to make some very in-depth code to allow a user to view their own chat and use the message id's to figure out where the newest message is.

———————————————————————-
Multi-Dimensional Arrays (How they work / How to index them):
———————————————————————-

Here we shall talk about arrays and how they work and how to index them.

Standard Arrays:


{
	"hello",
	"there",
	"my",
	"friends",
}

or


{
	user = "a_username",
	pass = 0123456789,
}
Multi-Dimensional Arrays:


mdarray = {
  {
	"first array",
	"second value",
	"third value",
  },
  {
	"second array",
	"second value",
	"third value",
  },
  {
	"third array",
	"second value",
	"third value",
  },
  {
	"fourth array",
	"second value",
	"third value",
  }
}

so for example: "first array" this value would be grabbed using: mdarray[1][1], but if we wanted the value just below the "third array" value then we would use: mdarray[3][2], so the first number in the square brackets is the simple arrays, and then second number is the value in that array, if we wanted to index the second array but not a specific array then we would use mdarray[2].

———————————————————————-
How to (A list of explanations on how to do things:
———————————————————————-

+ Friends lists/Followers:
As I am not keen on the whole friends thing I have made it so instead you can have followers and follow someone else. If you wish to use this as a way of a friends list or to display posts/tweets by your followers, then you will need to get the users following/friends list, and then loop through all posts, matching them with users in the friends list. This is all possible and pretty simple, you would need two loops both for loops of course. The first one will loop through all posts, and the second one to loop through your friends/following list, then if a username matches a following username, then add it to a new table etc.

+ Registering users:
Please make sure they add an email, as this is a big thing to have because the new forgotten password system uses emails to allow users to change their passwords by sending them an email, at least warn them if they don't add one.

+ Auto-Login:
To make an auto-login, store a username and password in a file and then on boot, open it and send it up.

+ Encryption:
This is automatic before any password goes up to the database, it is hashed using sha256 and then sent up, please note you do not need to hash anything before you send it up as it is done in the API. You would only need to hash it if you have modified the API.


———————————————————————-
All Possible Return Errors & Explanations:
———————————————————————-
All errors can occur from the database playing up as the smallest error will break the lua table, so if it does occur do add an issue on the GitHub repo.
Here is a list of errors and other possibilities other than a PHP error:

Could not create new post. -> This could be that the post data sent up may contain some kind of illegal character and the PHP script has escaped it.
Could not retrieve posts. -> This may be that there wasn't posts to display with your criteria.
Could not post new tweet. -> This could be that the post data sent up may contain some kind of illegal character and the PHP script has escaped it.
Could not get all posts/tweets from user. -> This may be that there wasn't tweets to display with your criteria.
Could not delete post. -> This can happen and this could mean you have deleted it before but the feed didn't update so you tried again, or you didn't supply the correct post/tweet ID.
Could not send chat message. -> This may be that there was an illegal character.
Could not get chat messages. -> This may be that there wasn't chat to display with your criteria.
Could not edit profile. -> This could be that the client has some how using the incorrect profile name.
Could not get profile.-> This could be that when editing the profile you broke the serialization.
Could not add friend. -> This could be that the lua table is broken therefore you can not add the friend.
Could not get friends list.-> Friends lua table may be broken.
You do not have permission to delete this. -> This will go when you do not have the correct permission to delete that post.
The username you wish to use is already taken! -> This can occur when registering and would mean your username is already taken.

Could not verify credentials. -> This is a login error, meaning your login is wrong.
Could not insert new user.-> This will be down to some kind of PHP error.
Edited on 20 March 2015 - 09:14 AM
oeed #2
Posted 20 March 2015 - 12:31 PM
Looks good!

Despite having a million other far more important things to do I'm going to work on this now for a bit.
DannySMc #3
Posted 20 March 2015 - 12:43 PM
Looks good!

Despite having a million other far more important things to do I'm going to work on this now for a bit.
Awesome!
_removed #4
Posted 20 March 2015 - 07:20 PM
Always impressed with what you do Danny, it never seems to fail.
MKlegoman357 #5
Posted 20 March 2015 - 08:18 PM
Nice you actually made it :lol:/>. People tend to drop these kind of projects. Anyway, suggestion time!

  1. textutils.serialize/unserialize actually support booleans, numbers, strings, nils and tables (unserialize supports almost any Lua code, without any libraries and such), so you can use textutils.unserialize on booleans to check the return value (in user.login for example).
  2. For all the functions that return a list of something: add two parameters - 'max' and 'page'. Returning everything is actually really bad, imagine how much data the server will need to send when there will be hundreds of tweets and such.. Those parameters would work like this:
  3. Imagine we have a list of tweet IDs here:
    
    * 123 (oldest)
    * 124
    * 125
    * 126
    * 127
    * 128 (latest)
    
    The 'max' value would indicate the maximum amount of tweets to return. So, if we set 'max' to two we would get the two latest tweets:
    
    * 127
    * 128
    
    To get the others, we could use the 'page' parameter. The bigger the page number the older messages we get. So, if 'max' is '2' and 'page' is '3':
    
    * 123
    * 124
    
    Examples:
    
    --# max: 3, page: 1
    * 126
    * 127
    * 128
    
    --# max: 3, page: 2
    * 123
    * 124
    * 125
    
  4. For tweets (messages) add a parameter ('from') to get the tweets counting from a specific tweet ID. Imagine we have the same list of tweet IDs:
  5. 
    * 123 (oldest)
    * 124
    * 125
    * 126
    * 127
    * 128 (latest)
    
    But on the user's computer the last cached tweet's ID is 124. So we need to get all the newer tweets (125, 126, 127 and 128). So we pass the parameter 'from' with a value '124' and we get those tweets:
    
    * 125
    * 126
    * 127
    * 128
    
    Together with my aforementioned 'max' and 'page' parameters it would work in reverse: it would first get the oldest messages and then the newer ones. Examples:
    
    --# from: 124, max: 2, page: 1
    * 125
    * 126
    
    --# from: 124, max: 2, page: 2
    * 127
    * 128
    
    --# from: 124, max: 3, page: 2
    * 128
    
  6. How about instead of returning true or an error message, return true + other data (app list for example) on success and false + error message when an error occurs.

And there's a 'bug':


function social.post.tweet(username, password, message)
  if message:len() >= 4096 then <--# shouldn't that be 255? :P/>
    return "Message is too big (Max: 255 chars)"
  end
Edited on 20 March 2015 - 07:25 PM
Mr. Bateman #6
Posted 20 March 2015 - 11:35 PM
And there's a 'bug':


function social.post.tweet(username, password, message)
  if message:len() >= 4096 then <--# shouldn't that be 255? :P/>/>
	return "Message is too big (Max: 255 chars)"
  end
It should be 256, due to the >= operator. 4096 is 256*16, so I'm guessing he's kind of accounting for non-existent unicode.
DannySMc #7
Posted 20 March 2015 - 11:55 PM
Always impressed with what you do Danny, it never seems to fail.

Haha it is buggy as hell :P/> but thanks!

-snip-

Thanks, yeah it has been an idea I wanted to do for a while! :P/> and yes I shall take your suggestions on and implement them as this was an idea I had previously (but in all honesty) it took me ages to make sure the PHP script returned the correct data in the correct format so got a little annoyed, and stopped, but yes I shall do this, although the friends functions have some issues too, which are pretty frustrating, but I should be able to make a work around.

And there's a 'bug':


function social.post.tweet(username, password, message)
  if message:len() >= 4096 then <--# shouldn't that be 255? :P/>/>/>
	return "Message is too big (Max: 255 chars)"
  end
It should be 256, due to the >= operator. 4096 is 256*16, so I'm guessing he's kind of accounting for non-existent unicode.
No this was me just forgetting :P/> I copied and pasted a lot of functions because they all output the same format of code so either a string or a lua table :P/> but yes will fix this.

One more guys, do you like the on-the-fly method to run the API? or shall I just keep it downloadable? Thanks
CrazedProgrammer #8
Posted 21 March 2015 - 06:14 PM
Always impressed with what you do Danny, it never seems to fail.

Haha it is buggy as hell :P/> but thanks!

-snip-

Thanks, yeah it has been an idea I wanted to do for a while! :P/> and yes I shall take your suggestions on and implement them as this was an idea I had previously (but in all honesty) it took me ages to make sure the PHP script returned the correct data in the correct format so got a little annoyed, and stopped, but yes I shall do this, although the friends functions have some issues too, which are pretty frustrating, but I should be able to make a work around.

And there's a 'bug':


function social.post.tweet(username, password, message)
  if message:len() >= 4096 then <--# shouldn't that be 255? :P/>/>/>/>/>
	return "Message is too big (Max: 255 chars)"
  end
It should be 256, due to the >= operator. 4096 is 256*16, so I'm guessing he's kind of accounting for non-existent unicode.
No this was me just forgetting :P/> I copied and pasted a lot of functions because they all output the same format of code so either a string or a lua table :P/> but yes will fix this.

One more guys, do you like the on-the-fly method to run the API? or shall I just keep it downloadable? Thanks
Please make/keep it downloadable. It's clumsy to download the API every time you want to use it.
If you have multiple files and you don't want to make an installation program, you can use my program Packager *hint*
Anyway, cool API.
If I have time enough then I'll probably make a program for this.
Edited on 21 March 2015 - 05:19 PM
DannySMc #9
Posted 21 March 2015 - 07:04 PM
Always impressed with what you do Danny, it never seems to fail.

Haha it is buggy as hell :P/> but thanks!

-snip-

Thanks, yeah it has been an idea I wanted to do for a while! :P/> and yes I shall take your suggestions on and implement them as this was an idea I had previously (but in all honesty) it took me ages to make sure the PHP script returned the correct data in the correct format so got a little annoyed, and stopped, but yes I shall do this, although the friends functions have some issues too, which are pretty frustrating, but I should be able to make a work around.

And there's a 'bug':


function social.post.tweet(username, password, message)
  if message:len() >= 4096 then <--# shouldn't that be 255? :P/>/>/>/>/>/>
	return "Message is too big (Max: 255 chars)"
  end
It should be 256, due to the >= operator. 4096 is 256*16, so I'm guessing he's kind of accounting for non-existent unicode.
No this was me just forgetting :P/> I copied and pasted a lot of functions because they all output the same format of code so either a string or a lua table :P/> but yes will fix this.

One more guys, do you like the on-the-fly method to run the API? or shall I just keep it downloadable? Thanks
Please make/keep it downloadable. It's clumsy to download the API every time you want to use it.
If you have multiple files and you don't want to make an installation program, you can use my program Packager *hint*
Anyway, cool API.
If I have time enough then I'll probably make a program for this.

Yeah okay, and if you do, give me credit, I hope you like it :P/>
MKlegoman357 #10
Posted 23 March 2015 - 08:10 PM
So, I actually started working on a GUI client for this, using Bedrock as the GUI framework. I can say that Bedrock is quite interesting to code. I've put the code on GitHub, although nothing is actually working yet, it's just me making a nice menu-thing for the program and making the Bedrock's drawing faster.
DannySMc #11
Posted 23 March 2015 - 10:16 PM
So, I actually started working on a GUI client for this, using Bedrock as the GUI framework. I can say that Bedrock is quite interesting to code. I've put the code on GitHub, although nothing is actually working yet, it's just me making a nice menu-thing for the program and making the Bedrock's drawing faster.
Awesome thank you for using it:P I hope it becomes like a Facebook kind of thing for CC :D/>
Tag365 #12
Posted 08 April 2015 - 10:43 PM
I made a basic client for you to test out Social Net. To download it run pastebin get 6GfTES26 SocialNet in your shell. It is also included with Lua Script System.

By the way, the chat is broken and thinks your credentials are invalid.
Edited on 08 April 2015 - 09:46 PM
DannySMc #13
Posted 09 April 2015 - 09:04 AM
I made a basic client for you to test out Social Net. To download it run pastebin get 6GfTES26 SocialNet in your shell. It is also included with Lua Script System.

By the way, the chat is broken and thinks your credentials are invalid.

Awesome, I was using this from the app store, very buggy you may want to make it touch screen.
Tag365 #14
Posted 09 April 2015 - 04:18 PM
It is not complete. I'm adding features and will make it so you can click on stuff and have it act like Lua Script System. I'm also making the Login screen consistent with the other menus.
DannySMc #15
Posted 09 April 2015 - 04:28 PM
It is not complete. I'm adding features and will make it so you can click on stuff and have it act like Lua Script System. I'm also making the Login screen consistent with the other menus.

Okay
Tag365 #16
Posted 09 April 2015 - 05:20 PM
By the way, what is the social.chat_global.new function supposed to return if you successfully sent a message? Also, does the social.chat_global.get function return a single dimensional table or two dimensional table if it successfully retrieves messages?
DannySMc #17
Posted 09 April 2015 - 05:26 PM
social.chat_global.new() should return true
social.chat_global.new() will return a two dimensional table,

{
  {
    "id",
    "username",
    "message",
    "timestamp",
  },
  {
    "message 2 etc.... (same as above)",
  },
}
Edited on 09 April 2015 - 03:26 PM
Tag365 #18
Posted 09 April 2015 - 05:35 PM
Well then I found a serious bug with your chat system. Using the social.chat_global.get function causes the assert at line 378 of your API to fail instead of returning the two dimensional array. It appears that it is triggering a credential error when I use it. Also, using the social.chat_global.new function returns a blank string instead of true. Can you fix this please so I can continue work on my client?
Edited on 09 April 2015 - 03:36 PM
DannySMc #19
Posted 09 April 2015 - 08:07 PM
Well then I found a serious bug with your chat system. Using the social.chat_global.get function causes the assert at line 378 of your API to fail instead of returning the two dimensional array. It appears that it is triggering a credential error when I use it. Also, using the social.chat_global.new function returns a blank string instead of true. Can you fix this please so I can continue work on my client?

Yeah will get onto this as soon as! Apologies!
Tag365 #20
Posted 13 April 2015 - 06:03 PM
Well then I found a serious bug with your chat system. Using the social.chat_global.get function causes the assert at line 378 of your API to fail instead of returning the two dimensional array. It appears that it is triggering a credential error when I use it. Also, using the social.chat_global.new function returns a blank string instead of true. Can you fix this please so I can continue work on my client?

Yeah will get onto this as soon as! Apologies!

The chat still doesn't work.
DannySMc #21
Posted 13 April 2015 - 10:14 PM
Well then I found a serious bug with your chat system. Using the social.chat_global.get function causes the assert at line 378 of your API to fail instead of returning the two dimensional array. It appears that it is triggering a credential error when I use it. Also, using the social.chat_global.new function returns a blank string instead of true. Can you fix this please so I can continue work on my client?

Yeah will get onto this as soon as! Apologies!

The chat still doesn't work.

In all honesty I have only started fixing it and updating the API to support asynchronous calls.
Tag365 #22
Posted 14 April 2015 - 03:46 PM
Can you tell me when it will be fixed?
DannySMc #23
Posted 14 April 2015 - 04:08 PM
Can you tell me when it will be fixed?

Well judging by the problems, hopefully soon, could you tell me what it is coming back as? like are you using assertion to make sure it is a table? or?
Tag365 #24
Posted 14 April 2015 - 04:11 PM
It is still saying socialnetAPI:378: assertion failed! Your API uses assertion, and it is failing at line 378.
Edited on 14 April 2015 - 02:13 PM
KRHN #25
Posted 14 April 2015 - 04:19 PM
Looks good, I will try it.
DannySMc #26
Posted 14 April 2015 - 05:35 PM
It is still saying socialnetAPI:378: assertion failed! Your API uses assertion, and it is failing at line 378.

Ahh thanks that means it isn't coming back as a table!
Tag365 #27
Posted 14 April 2015 - 05:50 PM
As I said the server appears to be not correctly handling the credentials sent from the client.
DannySMc #28
Posted 15 April 2015 - 11:06 PM
Hello everyone, if you are planning to develop for this then this is a new UPDATE, currently I am re-designing the API to work with a website I am building, and re-creating the whole chat system to work with a new web app instead. I will post here when I am done, I have already started it and nearly done. Will unveil it once it is ready! :D/>.
Tag365 #29
Posted 30 July 2015 - 07:11 AM
I'm still waiting on the next update. When will it be finished?
DannySMc #30
Posted 30 July 2015 - 09:01 AM
I'm still waiting on the next update. When will it be finished?
Being recoded currently.
Waitdev_ #31
Posted 30 July 2015 - 11:55 AM
has there been a program made from this?
this seems really cool :D/>
DannySMc #32
Posted 30 July 2015 - 12:40 PM
has there been a program made from this?
this seems really cool :D/>/>

MKLegoman is working on one, there is one made by Tag…? I am also making one currently that works with my OS, but no not any others. Why don't you have a go?:P/>

Also
To Tag: I have updated the chat thing? Did it ages ago?
Tag365 #33
Posted 30 July 2015 - 01:50 PM
I'm actually waiting for you to fix the API so I can fix my client. That is the reason I asked you.
DannySMc #34
Posted 30 July 2015 - 02:12 PM
I'm actually waiting for you to fix the API so I can fix my client. That is the reason I asked you.

What do you mean? what do you need fixing?:s The last thing I remember you saying was the Chat? which is fixed, what are you missing (what needs fixing)?
Tag365 #35
Posted 30 July 2015 - 05:38 PM
The server appears to be unable to be accessed.
Edited on 30 July 2015 - 03:58 PM
DannySMc #36
Posted 30 July 2015 - 07:10 PM
The server appears to be unable to be accessed.

What server?
Tag365 #37
Posted 31 July 2015 - 08:26 PM
I fixed my client, but the chat stuff is still broken. When I post a message the message body is the same as the sender of the message.
Edited on 31 July 2015 - 06:27 PM
DannySMc #38
Posted 31 July 2015 - 11:36 PM
I fixed my client, but the chat stuff is still broken. When I post a message the message body is the same as the sender of the message.

Hmm well MKLegoman has it working fine, so you may need to have a look at your code, are you doing asynchronously?
PokeAcer #39
Posted 31 August 2015 - 01:28 PM
This is pretty cool! :D/>
I have already thought of many uses - perhaps server updates on a monitor which checks for one account (please make it so you can get a user's posts w/o having to login) and then display it on screen :P/> - then you don't need to use RedNet, or have people look on a website.
DannySMc #40
Posted 31 August 2015 - 10:06 PM
This is pretty cool! :D/>
I have already thought of many uses - perhaps server updates on a monitor which checks for one account (please make it so you can get a user's posts w/o having to login) and then display it on screen :P/> - then you don't need to use RedNet, or have people look on a website.

Thanks! means a lot, and yeah I shall do, I have recoded the API :P/> So still working on some new updates, like sharing posts, liking posts, etc. So yeah I can do that :P/>, I use my new web browser for displaying updates for my server world :D/>. But I shall reply on here once I have added it?:D/>