Return semi-proper values from the protobuf HTTP API
This commit is contained in:
parent
dcbf801ecc
commit
dd2741a0c1
2
build.rs
2
build.rs
|
@ -41,7 +41,7 @@ fn main() {
|
||||||
config.type_attribute(".", "#[serde(rename_all = \"camelCase\")]");
|
config.type_attribute(".", "#[serde(rename_all = \"camelCase\")]");
|
||||||
|
|
||||||
tonic_build::configure()
|
tonic_build::configure()
|
||||||
.build_server(true)
|
.build_server(false)
|
||||||
.build_client(false)
|
.build_client(false)
|
||||||
.compile_with_config(
|
.compile_with_config(
|
||||||
config,
|
config,
|
||||||
|
|
|
@ -31,6 +31,12 @@ message Attributes {
|
||||||
int32 composure = 9;
|
int32 composure = 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Generic "did something succeed or not" response.
|
||||||
|
message ApiResult {
|
||||||
|
bool success = 1;
|
||||||
|
string error = 2;
|
||||||
|
}
|
||||||
|
|
||||||
//Update an attribute's dot amount. TODO rename to AttributesUpdate.
|
//Update an attribute's dot amount. TODO rename to AttributesUpdate.
|
||||||
message UpdateAttributeRequest {
|
message UpdateAttributeRequest {
|
||||||
string character_username = 1;
|
string character_username = 1;
|
||||||
|
@ -53,7 +59,6 @@ message SkillUpdate {
|
||||||
CofdSheet.Skill skill = 2;
|
CofdSheet.Skill skill = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//Partial update of a single skill dot amount.
|
//Partial update of a single skill dot amount.
|
||||||
message UpdateSkillValueRequest {
|
message UpdateSkillValueRequest {
|
||||||
string character_username = 1;
|
string character_username = 1;
|
||||||
|
@ -72,8 +77,4 @@ message SkillSpecializationsUpdate {
|
||||||
//Add a Condition to a Chronicles of Darkness character sheet.
|
//Add a Condition to a Chronicles of Darkness character sheet.
|
||||||
message Condition {
|
message Condition {
|
||||||
string name = 1;
|
string name = 1;
|
||||||
}
|
|
||||||
|
|
||||||
service CofdApi {
|
|
||||||
rpc UpdateSkillValue(UpdateSkillValueRequest) returns (CofdSheet.Skill);
|
|
||||||
}
|
}
|
117
src/grpc.rs
117
src/grpc.rs
|
@ -1,117 +0,0 @@
|
||||||
use crate::db::Dao;
|
|
||||||
use crate::errors::Error;
|
|
||||||
use crate::models::characters::Character;
|
|
||||||
use crate::models::proto::cofd::api::cofd_api_server::CofdApi;
|
|
||||||
use crate::models::proto::cofd::api::UpdateSkillValueRequest;
|
|
||||||
use crate::models::proto::cofd::cofd_sheet::Skill;
|
|
||||||
use crate::models::proto::cofd::*;
|
|
||||||
use crate::models::users::User;
|
|
||||||
use std::collections::btree_map::{Entry, OccupiedEntry};
|
|
||||||
use tonic::{Request, Response, Status};
|
|
||||||
|
|
||||||
/// Load the character belonging to the given user, as long as they're
|
|
||||||
/// the owner of that character. Returns an error if user is not
|
|
||||||
/// logged in, the owner of the character is not found, or the logged
|
|
||||||
/// in user does not have the permission to access this character.
|
|
||||||
async fn load_character(
|
|
||||||
conn: &sqlx::SqlitePool,
|
|
||||||
logged_in_user: Option<User>,
|
|
||||||
owner: &str,
|
|
||||||
character_id: i32,
|
|
||||||
) -> Result<Character, Error> {
|
|
||||||
let logged_in_user = logged_in_user.ok_or(Error::NotLoggedIn)?;
|
|
||||||
|
|
||||||
let character: Character = conn
|
|
||||||
.load_character(character_id)
|
|
||||||
.await?
|
|
||||||
.ok_or(Error::NotFound)?;
|
|
||||||
|
|
||||||
if &logged_in_user.username != owner {
|
|
||||||
return Err(Error::NoPermission);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(character)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn find_skill_entry<'a>(
|
|
||||||
sheet: &'a mut CofdSheet,
|
|
||||||
skill_name: &'a str,
|
|
||||||
) -> Option<OccupiedEntry<'a, String, Skill>> {
|
|
||||||
let all_skills = vec![
|
|
||||||
&mut sheet.mental_skills,
|
|
||||||
&mut sheet.physical_skills,
|
|
||||||
&mut sheet.social_skills,
|
|
||||||
];
|
|
||||||
|
|
||||||
// Search all skill lists for this value using "workaround" to
|
|
||||||
// break value from for loops.
|
|
||||||
let skill: Option<OccupiedEntry<_, _>> = 'l: loop {
|
|
||||||
for skill_map in all_skills {
|
|
||||||
if let Entry::Occupied(entry) = skill_map.entry(skill_name.to_owned()) {
|
|
||||||
break 'l Some(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break None;
|
|
||||||
};
|
|
||||||
|
|
||||||
skill
|
|
||||||
}
|
|
||||||
|
|
||||||
fn find_skill<'a>(sheet: &'a mut CofdSheet, skill_name: &'a str) -> Option<&'a mut Skill> {
|
|
||||||
find_skill_entry(sheet, skill_name).map(|entry| entry.into_mut())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct CofdApiService {
|
|
||||||
pub db: sqlx::SqlitePool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tonic::async_trait]
|
|
||||||
impl CofdApi for CofdApiService {
|
|
||||||
async fn update_skill_value(
|
|
||||||
&self,
|
|
||||||
request: Request<UpdateSkillValueRequest>, // Accept request of type HelloRequest
|
|
||||||
) -> Result<Response<Skill>, Status> {
|
|
||||||
let user_id: &str = request
|
|
||||||
.metadata()
|
|
||||||
.get("user_id")
|
|
||||||
.and_then(|user_id| user_id.to_str().ok())
|
|
||||||
.ok_or(Error::NotLoggedIn)?;
|
|
||||||
|
|
||||||
let logged_in_user = self
|
|
||||||
.db
|
|
||||||
.load_user(user_id)
|
|
||||||
.await
|
|
||||||
.map_err(|e| Error::from(e))?;
|
|
||||||
|
|
||||||
//Can use metadata map to add user id inside interceptor for auth.
|
|
||||||
let request = request.into_inner();
|
|
||||||
let mut character = load_character(
|
|
||||||
&self.db,
|
|
||||||
logged_in_user,
|
|
||||||
&request.character_username,
|
|
||||||
request.character_id,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let mut sheet: CofdSheet = character.try_deserialize()?;
|
|
||||||
let skill: Option<&mut Skill> = find_skill(&mut sheet, &request.skill_name);
|
|
||||||
|
|
||||||
skill
|
|
||||||
.map(|s| s.dots = request.skill_value)
|
|
||||||
.ok_or(Error::InvalidInput)?;
|
|
||||||
|
|
||||||
println!("updated skill value",);
|
|
||||||
|
|
||||||
character.update_data(sheet)?;
|
|
||||||
self.db
|
|
||||||
.update_character_sheet(&character)
|
|
||||||
.await
|
|
||||||
.map_err(|e| Error::from(e))?; //TODO maybe use crate Error for db
|
|
||||||
|
|
||||||
let reply = Skill::default();
|
|
||||||
|
|
||||||
Ok(Response::new(reply)) // Send back our formatted greeting
|
|
||||||
}
|
|
||||||
}
|
|
32
src/main.rs
32
src/main.rs
|
@ -18,25 +18,10 @@ use tonic::transport::Server;
|
||||||
pub mod catchers;
|
pub mod catchers;
|
||||||
pub mod db;
|
pub mod db;
|
||||||
pub mod errors;
|
pub mod errors;
|
||||||
pub mod grpc;
|
|
||||||
pub mod migrator;
|
pub mod migrator;
|
||||||
pub mod models;
|
pub mod models;
|
||||||
pub mod routes;
|
pub mod routes;
|
||||||
|
|
||||||
async fn make_tonic(db: sqlx::SqlitePool) -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
use crate::models::proto::cofd::api::cofd_api_server::CofdApiServer;
|
|
||||||
let addr = "[::1]:9090".parse()?;
|
|
||||||
let service = grpc::CofdApiService { db };
|
|
||||||
|
|
||||||
info!("Running Tonic");
|
|
||||||
Server::builder()
|
|
||||||
.add_service(CofdApiServer::new(service))
|
|
||||||
.serve(addr)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn make_rocket(database: sqlx::SqlitePool) -> Result<(), Box<dyn std::error::Error>> {
|
async fn make_rocket(database: sqlx::SqlitePool) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
info!("Running Rocket");
|
info!("Running Rocket");
|
||||||
let root_routes: Vec<rocket::Route> = {
|
let root_routes: Vec<rocket::Route> = {
|
||||||
|
@ -86,20 +71,5 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
|
||||||
let db = crate::db::create_pool(db_path).await?;
|
let db = crate::db::create_pool(db_path).await?;
|
||||||
|
|
||||||
tokio::select! {
|
make_rocket(db.clone()).await
|
||||||
result = make_rocket(db.clone()) => {
|
|
||||||
match result {
|
|
||||||
Ok(_) => info!("Shutting down Rocket."),
|
|
||||||
Err(e) => error!("Rocket error: {}", e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result = make_tonic(db) => {
|
|
||||||
match result {
|
|
||||||
Ok(_) => info!("Shutting down Tonic."),
|
|
||||||
Err(e) => error!("Tonic error: {}", e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,8 +146,8 @@ impl Character {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update the existing character with new serialized protobuf
|
/// Update the existing character with new serialized protobuf
|
||||||
/// data. Consumes the data.
|
/// data.
|
||||||
pub fn update_data<T>(&mut self, data: T) -> Result<(), Error>
|
pub fn update_data<T>(&mut self, data: &T) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
T: prost::Message + std::default::Default,
|
T: prost::Message + std::default::Default,
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
use crate::errors::Error;
|
use crate::errors::Error;
|
||||||
|
use prost::bytes::BytesMut;
|
||||||
use rocket::data::{Data, FromData, Outcome, ToByteUnit};
|
use rocket::data::{Data, FromData, Outcome, ToByteUnit};
|
||||||
|
use rocket::http::{ContentType, Status};
|
||||||
use rocket::request::Request;
|
use rocket::request::Request;
|
||||||
|
use rocket::response::status;
|
||||||
|
use rocket::response::{self, Responder, Response};
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
|
use std::io::Cursor;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
pub mod cofd;
|
pub mod cofd;
|
||||||
|
@ -10,7 +15,7 @@ pub mod cofd;
|
||||||
/// data submitted via POST using fetch API. Can automatically be
|
/// data submitted via POST using fetch API. Can automatically be
|
||||||
/// dereferenced into its wrapped type.
|
/// dereferenced into its wrapped type.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct Proto<T>(T)
|
pub(crate) struct Proto<T>(pub T)
|
||||||
where
|
where
|
||||||
T: prost::Message + Default;
|
T: prost::Message + Default;
|
||||||
|
|
||||||
|
@ -47,6 +52,22 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'r, T> Responder<'r, 'static> for Proto<T>
|
||||||
|
where
|
||||||
|
T: prost::Message + Default,
|
||||||
|
{
|
||||||
|
fn respond_to(self, req: &Request) -> response::Result<'static> {
|
||||||
|
let mut buf = BytesMut::with_capacity(std::mem::size_of_val(&self.0));
|
||||||
|
match self.0.encode(&mut buf) {
|
||||||
|
Ok(_) => Response::build()
|
||||||
|
.header(ContentType::new("application", "x-protobuf"))
|
||||||
|
.sized_body(buf.len(), Cursor::new(buf))
|
||||||
|
.ok(),
|
||||||
|
Err(e) => status::Custom(Status::InternalServerError, e.to_string()).respond_to(req),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Enable automatically calling methods on a decoded Proto instance.
|
/// Enable automatically calling methods on a decoded Proto instance.
|
||||||
impl<T> Deref for Proto<T>
|
impl<T> Deref for Proto<T>
|
||||||
where
|
where
|
||||||
|
|
|
@ -95,11 +95,11 @@ mod cofd {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/rpc/cofd/update_attribute_value", data = "<req>")]
|
#[post("/rpc/cofd/update_attribute_value", data = "<req>")]
|
||||||
pub(super) async fn update_attribute_value<'a>(
|
pub(super) async fn update_attribute_value(
|
||||||
req: Proto<UpdateAttributeRequest>,
|
req: Proto<UpdateAttributeRequest>,
|
||||||
conn: TenebrousDbConn<'_>,
|
conn: TenebrousDbConn<'_>,
|
||||||
logged_in_user: Option<&User>,
|
logged_in_user: Option<&User>,
|
||||||
) -> Result<&'a str, Error> {
|
) -> Result<Proto<ApiResult>, Error> {
|
||||||
let mut character = load_character(
|
let mut character = load_character(
|
||||||
&conn,
|
&conn,
|
||||||
logged_in_user,
|
logged_in_user,
|
||||||
|
@ -123,9 +123,12 @@ mod cofd {
|
||||||
_ => Err(Error::InvalidInput),
|
_ => Err(Error::InvalidInput),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
character.update_data(sheet)?;
|
character.update_data(&sheet)?;
|
||||||
conn.update_character_sheet(&character).await?;
|
conn.update_character_sheet(&character).await?;
|
||||||
Ok("lol")
|
Ok(Proto(ApiResult {
|
||||||
|
success: true,
|
||||||
|
error: "".to_string(),
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[patch(
|
#[patch(
|
||||||
|
@ -154,7 +157,7 @@ mod cofd {
|
||||||
skill_update.name, skill_update.skill
|
skill_update.name, skill_update.skill
|
||||||
);
|
);
|
||||||
|
|
||||||
character.update_data(sheet)?;
|
character.update_data(&sheet)?;
|
||||||
conn.update_character_sheet(&character).await?;
|
conn.update_character_sheet(&character).await?;
|
||||||
Ok("lol")
|
Ok("lol")
|
||||||
}
|
}
|
||||||
|
@ -164,7 +167,7 @@ mod cofd {
|
||||||
request: Proto<UpdateSkillValueRequest>,
|
request: Proto<UpdateSkillValueRequest>,
|
||||||
conn: TenebrousDbConn<'_>,
|
conn: TenebrousDbConn<'_>,
|
||||||
logged_in_user: Option<&User>,
|
logged_in_user: Option<&User>,
|
||||||
) -> Result<&'a str, Error> {
|
) -> Result<Proto<ApiResult>, Error> {
|
||||||
println!("{:#?}", request);
|
println!("{:#?}", request);
|
||||||
let mut character = load_character(
|
let mut character = load_character(
|
||||||
&conn,
|
&conn,
|
||||||
|
@ -175,17 +178,22 @@ mod cofd {
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let mut sheet: CofdSheet = character.try_deserialize()?;
|
let mut sheet: CofdSheet = character.try_deserialize()?;
|
||||||
let skill: Option<&mut Skill> = find_skill(&mut sheet, &request.skill_name);
|
|
||||||
|
|
||||||
skill
|
let mut skill: Option<&mut Skill> = find_skill(&mut sheet, &request.skill_name);
|
||||||
.map(|s| s.dots = request.skill_value)
|
if let Some(ref mut s) = skill {
|
||||||
.ok_or(Error::InvalidInput)?;
|
s.dots = request.skill_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
let updated_skill: Skill = skill.map(|s| s.clone()).ok_or(Error::InvalidInput)?;
|
||||||
|
|
||||||
println!("updated skill value",);
|
println!("updated skill value",);
|
||||||
|
|
||||||
character.update_data(sheet)?;
|
character.update_data(&sheet)?;
|
||||||
conn.update_character_sheet(&character).await?;
|
conn.update_character_sheet(&character).await?;
|
||||||
Ok("lol")
|
Ok(Proto(ApiResult {
|
||||||
|
success: true,
|
||||||
|
error: "".to_string(),
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[put("/cofd/<owner>/<character_id>/conditions", data = "<info>")]
|
#[put("/cofd/<owner>/<character_id>/conditions", data = "<info>")]
|
||||||
|
|
|
@ -92,6 +92,30 @@ export namespace Attributes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class ApiResult extends jspb.Message {
|
||||||
|
getSuccess(): boolean;
|
||||||
|
setSuccess(value: boolean): void;
|
||||||
|
|
||||||
|
getError(): string;
|
||||||
|
setError(value: string): void;
|
||||||
|
|
||||||
|
serializeBinary(): Uint8Array;
|
||||||
|
toObject(includeInstance?: boolean): ApiResult.AsObject;
|
||||||
|
static toObject(includeInstance: boolean, msg: ApiResult): ApiResult.AsObject;
|
||||||
|
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
|
||||||
|
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
|
||||||
|
static serializeBinaryToWriter(message: ApiResult, writer: jspb.BinaryWriter): void;
|
||||||
|
static deserializeBinary(bytes: Uint8Array): ApiResult;
|
||||||
|
static deserializeBinaryFromReader(message: ApiResult, reader: jspb.BinaryReader): ApiResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace ApiResult {
|
||||||
|
export type AsObject = {
|
||||||
|
success: boolean,
|
||||||
|
error: string,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class UpdateAttributeRequest extends jspb.Message {
|
export class UpdateAttributeRequest extends jspb.Message {
|
||||||
getCharacterUsername(): string;
|
getCharacterUsername(): string;
|
||||||
setCharacterUsername(value: string): void;
|
setCharacterUsername(value: string): void;
|
||||||
|
|
|
@ -16,6 +16,7 @@ var global = Function('return this')();
|
||||||
|
|
||||||
var cofd_pb = require('./cofd_pb.js');
|
var cofd_pb = require('./cofd_pb.js');
|
||||||
goog.object.extend(proto, cofd_pb);
|
goog.object.extend(proto, cofd_pb);
|
||||||
|
goog.exportSymbol('proto.models.proto.cofd.api.ApiResult', null, global);
|
||||||
goog.exportSymbol('proto.models.proto.cofd.api.Attributes', null, global);
|
goog.exportSymbol('proto.models.proto.cofd.api.Attributes', null, global);
|
||||||
goog.exportSymbol('proto.models.proto.cofd.api.BasicInfo', null, global);
|
goog.exportSymbol('proto.models.proto.cofd.api.BasicInfo', null, global);
|
||||||
goog.exportSymbol('proto.models.proto.cofd.api.Condition', null, global);
|
goog.exportSymbol('proto.models.proto.cofd.api.Condition', null, global);
|
||||||
|
@ -66,6 +67,27 @@ if (goog.DEBUG && !COMPILED) {
|
||||||
*/
|
*/
|
||||||
proto.models.proto.cofd.api.Attributes.displayName = 'proto.models.proto.cofd.api.Attributes';
|
proto.models.proto.cofd.api.Attributes.displayName = 'proto.models.proto.cofd.api.Attributes';
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Generated by JsPbCodeGenerator.
|
||||||
|
* @param {Array=} opt_data Optional initial data array, typically from a
|
||||||
|
* server response, or constructed directly in Javascript. The array is used
|
||||||
|
* in place and becomes part of the constructed object. It is not cloned.
|
||||||
|
* If no data is provided, the constructed object will be empty, but still
|
||||||
|
* valid.
|
||||||
|
* @extends {jspb.Message}
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
proto.models.proto.cofd.api.ApiResult = function(opt_data) {
|
||||||
|
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
|
||||||
|
};
|
||||||
|
goog.inherits(proto.models.proto.cofd.api.ApiResult, jspb.Message);
|
||||||
|
if (goog.DEBUG && !COMPILED) {
|
||||||
|
/**
|
||||||
|
* @public
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
proto.models.proto.cofd.api.ApiResult.displayName = 'proto.models.proto.cofd.api.ApiResult';
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Generated by JsPbCodeGenerator.
|
* Generated by JsPbCodeGenerator.
|
||||||
* @param {Array=} opt_data Optional initial data array, typically from a
|
* @param {Array=} opt_data Optional initial data array, typically from a
|
||||||
|
@ -815,6 +837,166 @@ proto.models.proto.cofd.api.Attributes.prototype.setComposure = function(value)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (jspb.Message.GENERATE_TO_OBJECT) {
|
||||||
|
/**
|
||||||
|
* Creates an object representation of this proto.
|
||||||
|
* Field names that are reserved in JavaScript and will be renamed to pb_name.
|
||||||
|
* Optional fields that are not set will be set to undefined.
|
||||||
|
* To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
|
||||||
|
* For the list of reserved names please see:
|
||||||
|
* net/proto2/compiler/js/internal/generator.cc#kKeyword.
|
||||||
|
* @param {boolean=} opt_includeInstance Deprecated. whether to include the
|
||||||
|
* JSPB instance for transitional soy proto support:
|
||||||
|
* http://goto/soy-param-migration
|
||||||
|
* @return {!Object}
|
||||||
|
*/
|
||||||
|
proto.models.proto.cofd.api.ApiResult.prototype.toObject = function(opt_includeInstance) {
|
||||||
|
return proto.models.proto.cofd.api.ApiResult.toObject(opt_includeInstance, this);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static version of the {@see toObject} method.
|
||||||
|
* @param {boolean|undefined} includeInstance Deprecated. Whether to include
|
||||||
|
* the JSPB instance for transitional soy proto support:
|
||||||
|
* http://goto/soy-param-migration
|
||||||
|
* @param {!proto.models.proto.cofd.api.ApiResult} msg The msg instance to transform.
|
||||||
|
* @return {!Object}
|
||||||
|
* @suppress {unusedLocalVariables} f is only used for nested messages
|
||||||
|
*/
|
||||||
|
proto.models.proto.cofd.api.ApiResult.toObject = function(includeInstance, msg) {
|
||||||
|
var f, obj = {
|
||||||
|
success: jspb.Message.getBooleanFieldWithDefault(msg, 1, false),
|
||||||
|
error: jspb.Message.getFieldWithDefault(msg, 2, "")
|
||||||
|
};
|
||||||
|
|
||||||
|
if (includeInstance) {
|
||||||
|
obj.$jspbMessageInstance = msg;
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserializes binary data (in protobuf wire format).
|
||||||
|
* @param {jspb.ByteSource} bytes The bytes to deserialize.
|
||||||
|
* @return {!proto.models.proto.cofd.api.ApiResult}
|
||||||
|
*/
|
||||||
|
proto.models.proto.cofd.api.ApiResult.deserializeBinary = function(bytes) {
|
||||||
|
var reader = new jspb.BinaryReader(bytes);
|
||||||
|
var msg = new proto.models.proto.cofd.api.ApiResult;
|
||||||
|
return proto.models.proto.cofd.api.ApiResult.deserializeBinaryFromReader(msg, reader);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserializes binary data (in protobuf wire format) from the
|
||||||
|
* given reader into the given message object.
|
||||||
|
* @param {!proto.models.proto.cofd.api.ApiResult} msg The message object to deserialize into.
|
||||||
|
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
|
||||||
|
* @return {!proto.models.proto.cofd.api.ApiResult}
|
||||||
|
*/
|
||||||
|
proto.models.proto.cofd.api.ApiResult.deserializeBinaryFromReader = function(msg, reader) {
|
||||||
|
while (reader.nextField()) {
|
||||||
|
if (reader.isEndGroup()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
var field = reader.getFieldNumber();
|
||||||
|
switch (field) {
|
||||||
|
case 1:
|
||||||
|
var value = /** @type {boolean} */ (reader.readBool());
|
||||||
|
msg.setSuccess(value);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
var value = /** @type {string} */ (reader.readString());
|
||||||
|
msg.setError(value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
reader.skipField();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serializes the message to binary data (in protobuf wire format).
|
||||||
|
* @return {!Uint8Array}
|
||||||
|
*/
|
||||||
|
proto.models.proto.cofd.api.ApiResult.prototype.serializeBinary = function() {
|
||||||
|
var writer = new jspb.BinaryWriter();
|
||||||
|
proto.models.proto.cofd.api.ApiResult.serializeBinaryToWriter(this, writer);
|
||||||
|
return writer.getResultBuffer();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serializes the given message to binary data (in protobuf wire
|
||||||
|
* format), writing to the given BinaryWriter.
|
||||||
|
* @param {!proto.models.proto.cofd.api.ApiResult} message
|
||||||
|
* @param {!jspb.BinaryWriter} writer
|
||||||
|
* @suppress {unusedLocalVariables} f is only used for nested messages
|
||||||
|
*/
|
||||||
|
proto.models.proto.cofd.api.ApiResult.serializeBinaryToWriter = function(message, writer) {
|
||||||
|
var f = undefined;
|
||||||
|
f = message.getSuccess();
|
||||||
|
if (f) {
|
||||||
|
writer.writeBool(
|
||||||
|
1,
|
||||||
|
f
|
||||||
|
);
|
||||||
|
}
|
||||||
|
f = message.getError();
|
||||||
|
if (f.length > 0) {
|
||||||
|
writer.writeString(
|
||||||
|
2,
|
||||||
|
f
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* optional bool success = 1;
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
proto.models.proto.cofd.api.ApiResult.prototype.getSuccess = function() {
|
||||||
|
return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 1, false));
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {boolean} value
|
||||||
|
* @return {!proto.models.proto.cofd.api.ApiResult} returns this
|
||||||
|
*/
|
||||||
|
proto.models.proto.cofd.api.ApiResult.prototype.setSuccess = function(value) {
|
||||||
|
return jspb.Message.setProto3BooleanField(this, 1, value);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* optional string error = 2;
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
proto.models.proto.cofd.api.ApiResult.prototype.getError = function() {
|
||||||
|
return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, ""));
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} value
|
||||||
|
* @return {!proto.models.proto.cofd.api.ApiResult} returns this
|
||||||
|
*/
|
||||||
|
proto.models.proto.cofd.api.ApiResult.prototype.setError = function(value) {
|
||||||
|
return jspb.Message.setProto3StringField(this, 2, value);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (jspb.Message.GENERATE_TO_OBJECT) {
|
if (jspb.Message.GENERATE_TO_OBJECT) {
|
||||||
/**
|
/**
|
||||||
* Creates an object representation of this proto.
|
* Creates an object representation of this proto.
|
||||||
|
|
|
@ -1,24 +1,31 @@
|
||||||
import * as jspb from "google-protobuf";
|
import * as jspb from "google-protobuf";
|
||||||
import { UpdateAttributeRequest, UpdateSkillValueRequest } from "../_proto/cofd_api_pb";
|
import { CofdSheet } from "../_proto/cofd_pb";
|
||||||
|
import { Skills, ApiResult, UpdateAttributeRequest, UpdateSkillValueRequest } from "../_proto/cofd_api_pb";
|
||||||
|
|
||||||
const PROTOBUF_CONTENT_TYPE = { 'Content-Type': 'application/x-protobuf' };
|
const PROTOBUF_CONTENT_TYPE = { 'Content-Type': 'application/x-protobuf' };
|
||||||
|
|
||||||
async function makeRequest<T extends jspb.Message>(uri: string, params: T) {
|
function staticImplements<T>() {
|
||||||
|
return <U extends T>(constructor: U) => { constructor };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function makeRequest<T extends jspb.Message>(uri: string, params: T): Promise<Uint8Array> {
|
||||||
let resp = await fetch(uri, {
|
let resp = await fetch(uri, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { ...PROTOBUF_CONTENT_TYPE },
|
headers: { ...PROTOBUF_CONTENT_TYPE },
|
||||||
body: params.serializeBinary()
|
body: params.serializeBinary()
|
||||||
}).then(async resp => {
|
|
||||||
console.log("resp is", await resp.text());
|
|
||||||
}).catch(async err => {
|
|
||||||
console.log("err is", err.text());
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const data = await resp.arrayBuffer();
|
||||||
|
return new Uint8Array(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateSkillValue(params: UpdateSkillValueRequest) {
|
export async function updateSkillValue(params: UpdateSkillValueRequest): Promise<ApiResult> {
|
||||||
await makeRequest('/api/rpc/cofd/update_skill_value', params);
|
let data = await makeRequest('/api/rpc/cofd/update_skill_value', params);
|
||||||
|
return ApiResult.deserializeBinary(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateAttributeValue(params: UpdateAttributeRequest) {
|
export async function updateAttributeValue(params: UpdateAttributeRequest): Promise<ApiResult> {
|
||||||
await makeRequest('/api/rpc/cofd/update_attribute_value', params);
|
let data = await makeRequest('/api/rpc/cofd/update_attribute_value', params);
|
||||||
|
return ApiResult.deserializeBinary(data);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,8 @@ import * as api from "../api";
|
||||||
params.setCharacterId(parseInt(CHARACTER_ID));
|
params.setCharacterId(parseInt(CHARACTER_ID));
|
||||||
params.setAttributeName(attribute);
|
params.setAttributeName(attribute);
|
||||||
params.setAttributeValue(newValue);
|
params.setAttributeValue(newValue);
|
||||||
await api.updateAttributeValue(params);
|
let resp = await api.updateAttributeValue(params);
|
||||||
|
console.log("got a response back", resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
Array.from(attributeInputs).forEach(input => {
|
Array.from(attributeInputs).forEach(input => {
|
||||||
|
@ -50,7 +51,9 @@ import * as api from "../api";
|
||||||
params.setSkillName(attribute);
|
params.setSkillName(attribute);
|
||||||
params.setSkillValue(newValue);
|
params.setSkillValue(newValue);
|
||||||
|
|
||||||
await api.updateSkillValue(params);
|
let resp = await api.updateSkillValue(params);
|
||||||
|
|
||||||
|
console.log("got a response back", resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
Array.from(skillInputs).forEach(input => {
|
Array.from(skillInputs).forEach(input => {
|
||||||
|
|
Loading…
Reference in New Issue