New Features
What feature(s) did you add?
On the basis of the previous version, the following features were updated: steemconnect login, comment, vote, release function
How did you implement it/them?
This function is updated, mainly related to two files.
//
// SteemClient.swift
// SteemThink
//
// Created by zhouzhiwei on 2018/2/22.
// Copyright © 2018年 zijinph. All rights reserved.
//
import UIKit
import MBProgressHUD
let baseURL:String = "https://v2.steemconnect.com"
let appId:String = ""
//GET /get_discussions_by_trending
let discussions_by_trending = "https://api.steemjs.com/get_discussions_by_trending?"
//GET /get_discussions_by_created
let discussions_by_created = "https://api.steemjs.com/get_discussions_by_created?"
//GET /get_discussions_by_hot
let discussions_by_hot = "https://api.steemjs.com/get_discussions_by_hot?"
//GET /get_accounts
let get_accounts = "https://api.steemjs.com/get_accounts?"
let get_content_replies = "https://api.steemjs.com/get_content_replies?"
let get_login_url = "https://v2.steemconnect.com/oauth2/authorize?client_id=steemthink.com&redirect_uri=https://cnsteem.github.io/sc2-angular&scope=vote,comment"
//POST /broadcast
let post_broadcast = "https://v2.steemconnect.com/api/broadcast/"
class STClient: NSObject {
typealias STClientCallBack = (_ response: Any?,_ error: Error?)->()
//MARK: - vote
class func vote(
voter:String,
author:String,
permlink:String,
weight:NSInteger,
finished:@escaping STClientCallBack){
let param = ["voter": voter,
"author": author,
"permlink":permlink,
"weight":weight,
] as [String : Any]
self.broadcast(body: ["operations":[["vote",param]]],finished: finished)
}
//MARK: - post&comment
class func comment(
parentAuthor:String,
parentPermlink:String,
author:String,
permlink:String,
body:String,
finished:@escaping STClientCallBack) {
let param = ["parent_author": parentAuthor,
"parent_permlink": parentPermlink,
"author":author,
"permlink":permlink,
"title":"",
"body":body,
"json_metadata": ""]
self.broadcast(body: ["operations":[["comment",param]]],finished: finished)
}
class func broadcast(body:Dictionary<String, Any>,
finished:@escaping STClientCallBack) {
// print("jsonData ==============="+"\(NSDictionary_STExtension.getJSONStringFromDictionary(dictionary: body))")
self.post(url: post_broadcast, body: body, finished: finished)
}
class func post(url:String,body:Dictionary<String, Any>,finished:@escaping STClientCallBack) -> Void {
let client = STAFNetworkTools.sharedTools;
// Set the requested header tag
client.requestSerializer.setValue(UserDataManager.sharedInstance.getToken(), forHTTPHeaderField: "Authorization")
client.request(method: .POST, urlString: url, parameters: body as AnyObject) { (response, error) in
finished(response,error)
}
}
class func get(url:String!,parameters:AnyObject?,to:UIView?,finished:@escaping STClientCallBack){
var hud:MBProgressHUD?
if (to != nil){
hud = MBProgress_STExtension.ST_ShowHUDAddedToView(view: to!, title: "", animated: true)
}
STAFNetworkTools.sharedTools.request(method: .GET, urlString: url, parameters: parameters) { (response: Any?,error: Error?) in
if (hud != nil) {
hud?.hide(animated: true)
}
if (error != nil) && (to != nil) {
MBProgress_STExtension.ST_ShowHUDHidAfterSecondWithMsgType(title: (error?.localizedDescription)!, view: to!, afterSecond: 1.5, msgType: STMBProgress.Error)
}
finished(response,error)
}
}
}
//
// AFNetworkTools.swift
// SteemThink
//
// Created by zhouzhiwei on 2018/2/22.
// Copyright © 2018 zijinph. All rights reserved.
//
import UIKit
import AFNetworking
/// Request method
/// - GET: get
/// - POST: post
enum AFRequestMethod: String {
case GET = "GET"
case POST = "POST"
}
class STAFNetworkTools: AFHTTPSessionManager {
static let sharedTools: STAFNetworkTools = {
let instance = STAFNetworkTools()
instance.responseSerializer.acceptableContentTypes?.insert("text/html")
instance.responseSerializer.acceptableContentTypes?.insert("text/plain")
instance.requestSerializer = AFJSONRequestSerializer.init()
instance.requestSerializer.timeoutInterval = 20.0
return instance
}()
// (response: AnyObject?, error: NSError?)->()
typealias AFNRequestCallBack = (_ response: Any?,_ error: Error?)->()
///
/// - parameter urlString: request address
/// - parameter parameters: Request parameters
/// - parameter finished: The callback for the success or failure of the request
func request(method: AFRequestMethod = .GET, urlString: String, parameters: AnyObject?, finished:@escaping AFNRequestCallBack){
print("urlString ============ " + urlString)
print("parameters ============ " + String(describing: parameters))
// dataTaskWithHttp is written in the. M file
// corresponds to Swift, is a private modification method
// Define the closure for which the request succeeded
let success = { (dataTask: URLSessionDataTask, responseObject: Any?) -> Void in
print("responseObject =========" + "\(String(describing: responseObject))")
finished(responseObject, nil)
}
// Define the closure of the request failed
let failure = { (dataTask: URLSessionDataTask?, error: Error) -> Void in
print("request Error =========" + error.localizedDescription)
finished(nil, error)
}
if method == .GET {
get(urlString,parameters:parameters,progress:nil,success:success,failure:failure)
}else{
post(urlString, parameters: parameters, progress: nil, success:success, failure: failure)
}
}
func requestBack(method: AFRequestMethod = .GET, urlString: String, parameters: AnyObject?, finished:@escaping AFNRequestCallBack) -> URLSessionDataTask{
print("urlString ============ " + urlString)
print("parameters ============ " + String(describing: parameters))
// dataTaskWithHttp is written in the. M file
// corresponds to Swift, is a private modification method
// Define the closure for which the request succeeded
let success = { (dataTask: URLSessionDataTask, responseObject: Any?) -> Void in
print("responseObject =========" + "\(String(describing: responseObject))")
finished(responseObject, nil)
}
// Define the closure of the request failed
let failure = { (dataTask: URLSessionDataTask?, error: Error) -> Void in
print("request Error =========" + error.localizedDescription)
finished(nil, error)
}
if method == .GET {
return get(urlString,parameters:parameters,progress:nil,success:success,failure:failure)!
}else{
return post(urlString, parameters: parameters, progress: nil, success:success, failure: failure)!
}
}
/// send request (upload file)
func requestWithData(data: NSData, name: String, urlString: String, parameters: AnyObject?, finished:@escaping AFNRequestCallBack) {
// Define the closure for which the request succeeded
let success = { (dataTask: URLSessionDataTask, responseObject: AnyObject?) -> Void in
finished(responseObject, nil)
}
// Define the closure of the request failed
let failure = { (dataTask: URLSessionDataTask?, error: NSError) -> Void in
finished(nil, error)
}
post(urlString, parameters: parameters, constructingBodyWith: { (formData) -> Void in
formData.appendPart(withFileData: data as Data, name: name, fileName: "aa", mimeType: "application/octet-stream")
}, progress: nil, success: success as? (URLSessionDataTask, Any?) -> Void, failure: (failure as! (URLSessionDataTask?, Error) -> Void))
}
}
The following is a detailed code description
The interface part is derived from the sc2.js code in steemconnect-sdk (https://github.com/steemit/steemconnect-sdk/blob/master/src/sc2.js).
Conversion process :
1. HTTPS request header
js:
headers:{
Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/json',
Authorization: this.options.accessToken,
}
iOS:
instance.responseSerializer.acceptableContentTypes?.insert("text/html")
instance.responseSerializer.acceptableContentTypes?.insert("text/plain")
instance.requestSerializer = AFJSONRequestSerializer.init()
And we have to set the token, the token is obtained from the login screen callback
let client = STAFNetworkTools.sharedTools;
// Set request header token
client.requestSerializer.setValue(UserDataManager.sharedInstance.getToken(), forHTTPHeaderField: "Authorization")
2. Commenting and publishing articles (Publishing articles and comments is an API, which is a little strange)
js:
SteemConnect.prototype.broadcast = function broadcast(operations, cb) {
return this.send('broadcast', 'POST', { operations }, cb);
};
SteemConnect.prototype.comment = function comment(
parentAuthor,
parentPermlink,
author,
permlink,
title,
body,
jsonMetadata,
cb
) {
const params = {
parent_author: parentAuthor,
parent_permlink: parentPermlink,
author,
permlink,
title,
body,
json_metadata: JSON.stringify(jsonMetadata),
};
return this.broadcast([['comment', params]], cb);
};
iOS:
class func comment(
parentAuthor:String,
parentPermlink:String,
author:String,
permlink:String,
body:String,
finished:@escaping STClientCallBack) {
let param = ["parent_author": parentAuthor,
"parent_permlink": parentPermlink,
"author":author,
"permlink":permlink,
"title":"",
"body":body,
"json_metadata": ""]
self.broadcast(body: ["operations":[["comment",param]]],finished: finished)
}
class func broadcast(body:Dictionary<String, Any>,
finished:@escaping STClientCallBack) {
// print("jsonData ==============="+"\(NSDictionary_STExtension.getJSONStringFromDictionary(dictionary: body))")
self.post(url: post_broadcast, body: body, finished: finished)
}
The contents of the body should be in strict accordance with ["operations": [["comment", param]]] This format, otherwise it will request failure.
3. vote
js:
SteemConnect.prototype.vote = function vote(voter, author, permlink, weight, cb) {
const params = {
voter,
author,
permlink,
weight,
};
return this.broadcast([['vote', params]], cb);
};
iOS:
//MARK: - vote
class func vote(
voter:String,
author:String,
permlink:String,
weight:NSInteger,
finished:@escaping STClientCallBack){
let param = ["voter": voter,
"author": author,
"permlink":permlink,
"weight":weight,
] as [String : Any]
self.broadcast(body: ["operations":[["vote",param]]],finished: finished)
}
Posted on Utopian.io - Rewarding Open Source Contributors