So here's what my code (pretty much) looks like to create a message using the google-api-ruby-client:
service ||= Google::Apis::GmailV1::GmailService.new
message = RMail::Message.new
message.header['To'] = params[:gmail][:to]
message.header['From'] = current_user_google_user_id
message.header['Subject'] = params[:gmail][:subject]
message.header['Subject'] = params[:gmail][:subject]
message.body = params[:gmail][:body]
service.send_user_message(
current_user_google_user_id,
upload_source: StringIO.new(message.to_s),
content_type: 'message/rfc822',
thread_id: params[:gmail][:thread_id]
)
It obviously fails because of where I have thread_id. If I remove that line, things work fine, but I'm not able to keep things scoped to a thread. How should I be passing the thread ID to the GmailService?
Looking at the source on GitHub for send_user_message shows that it doesn't take a thread_id as a parameter. However the Message class does have it as an attribute.
So perhaps trying this should work:
service ||= Google::Apis::GmailV1::GmailService.new
message = RMail::Message.new
message.header['To'] = params[:gmail][:to]
message.header['From'] = current_user_google_user_id
message.header['Subject'] = params[:gmail][:subject]
message.header['Subject'] = params[:gmail][:subject]
message.body = params[:gmail][:body]
message.thread_id = params[:gmail][:thread_id]
service.send_user_message(
current_user_google_user_id,
upload_source: StringIO.new(message.to_s),
content_type: 'message/rfc822'
)
Related
I've just created a new Google Analytics property and it now defaults to data streams instead of views.
I had some code that was fetching reports through the API that I now need to updated to work with those data streams instead of views since there are not views anymore.
I've looked in the docs but i don't see anything related to data streams, anybody knows how this is done now?
Here's my current code that works with a view ID (I'm using the ruby google-api-client gem):
VIEW_ID = "XXXXXX"
SCOPE = 'https://www.googleapis.com/auth/analytics.readonly'
client = AnalyticsReportingService.new
#server to server auth mechanism using a service account
#creds = ServiceAccountCredentials.make_creds({:json_key_io => File.open('account.json'), :scope => SCOPE})
#creds.sub = "myserviceaccount#example.iam.gserviceaccount.com"
client.authorization = #creds
#metrics
metric_views = Metric.new
metric_views.expression = "ga:pageviews"
metric_unique_views = Metric.new
metric_unique_views.expression = "ga:uniquePageviews"
#dimensions
dimension = Dimension.new
dimension.name = "ga:hostname"
#range
range = DateRange.new
range.start_date = start_date
range.end_date = end_date
#sort
orderby = OrderBy.new
orderby.field_name = "ga:pageviews"
orderby.sort_order = 'DESCENDING'
rr = ReportRequest.new
rr.view_id = VIEW_ID
rr.metrics = [metric_views, metric_unique_views]
rr.dimensions = [dimension]
rr.date_ranges = [range]
rr.order_bys = [orderby]
grr = GetReportsRequest.new
grr.report_requests = [rr]
response = client.batch_get_reports(grr)
I would expect that there would be a stream_id property on the ReportRequest object that I could use instead of the view_id but that's not the case.
Your existing code uses the Google Analytics Reporting api to extract data from a Universal analytics account.
Your new Google analytics property is a Google Analytics GA4 account. To extract data from that you need to use the Google analytics data api These are two completely different systems. You will not be able to just port it.
You can find info on the new api and new library here: Ruby Client for the Google Analytics Data API
$ gem install google-analytics-data
Thanks to Linda's answer i was able to get it working, here's the same code ported to the data API, it might end up being useful to someone:
client = Google::Analytics::Data.analytics_data do |config|
config.credentials = "account.json"
end
metric_views = Google::Analytics::Data::V1beta::Metric.new(name: "screenPageViews")
metric_unique_views = Google::Analytics::Data::V1beta::Metric.new(name: "totalUsers")
dimension = Google::Analytics::Data::V1beta::Dimension.new(name: "hostName")
range = Google::Analytics::Data::V1beta::DateRange.new(start_date: start_date, end_date: end_date)
order_dim = Google::Analytics::Data::V1beta::OrderBy::DimensionOrderBy.new(dimension_name: "screenPageViews")
orderby = Google::Analytics::Data::V1beta::OrderBy.new(desc: true, dimension: order_dim)
request = Google::Analytics::Data::V1beta::RunReportRequest.new(
property: "properties/#{PROPERTY_ID}",
metrics: [metric_views, metric_unique_views],
dimensions: [dimension],
date_ranges: [range],
order_bys: [orderby]
)
response = client.run_report request
why okhttp4.x use the replaceWith to forbid developer to get response's code like response.code(). Deprecated( message = "moved to val", replaceWith = ReplaceWith(expression = "code"), level = DeprecationLevel.ERROR)
why okhttp4.x use the replaceWith to forbid developer to get response's code like response.code(). Deprecated( message = "moved to val", replaceWith = ReplaceWith(expression = "code"), level = DeprecationLevel.ERROR)
In OkHttp 4.x, the Response.code() method has been deprecated in favor of using the code property. This change improves the readability and consistency of the code. To get the response code, use response.code instead of response.code().
I am currently testing IBM MQ request using JSR223 sampler in JMeter. My scenario here is, i need to sent the request to one queue name(Queue.In) and retrieve the response from another queuename(Queue.out). Now i am able to retrieve the response from Queue.out but i am not sure it's extracting the correct message that i have sent or some other message request is in queue already(FIFO model).
May, i know how to modify my below code to send the message id/correlation id to Queue.IN and retrieve the same message id/corelation id from Queue.out or Please do suggest if there is any better approach to extract the same messages from Queue.out.
import com.ibm.mq.MQAsyncStatus
import com.ibm.mq.MQMessage
import com.ibm.mq.MQPutMessageOptions
import com.ibm.mq.MQQueueManager
import com.ibm.mq.constants.CMQC
import com.ibm.mq.constants.MQConstants
import com.ibm.mq.headers.MQRFH2
def mqProps = new Hashtable<String, Object>()
mqProps.put(MQConstants.CHANNEL_PROPERTY, 'xxxx')
mqProps.put(MQConstants.PORT_PROPERTY, 1414)
mqProps.put(MQConstants.HOST_NAME_PROPERTY, 'xxx')
def hostName = "${p_hostName}"
def hostPort = ${p_hostPort}
def channelName = "${p_channelName}"
def qManager = "${p_queueManagerName}"
def queueName = "${p_queueName}"
def qMgr = new MQQueueManager(qManager, mqProps)
def openOptions = MQConstants.MQOO_OUTPUT | MQConstants.MQOO_INPUT_AS_Q_DEF
def queue = qMgr.accessQueue(queueName, openOptions)
def pmo = new MQPutMessageOptions()
pmo.options = MQConstants.MQPMO_ASYNC_RESPONSE
def message = new MQMessage()
message.format = CMQC.MQFMT_RF_HEADER_2
def rfh2 = new MQRFH2()
rfh2.setEncoding(CMQC.MQENC_NATIVE)
rfh2.setCodedCharSetId(CMQC.MQCCSI_INHERIT)
rfh2.setFormat(CMQC.MQFMT_STRING)
rfh2.setNameValueCCSID(1208)
rfh2.setFieldValue('usr', '${Var1}', '${Var2}')
rfh2.write(message)
message.writeString('''${request_payload}''')
queue.put(message, pmo)
queue.close()
MQAsyncStatus asyncStatus = qMgr.getAsyncStatus()
log.info('Successfully published: ' + asyncStatus.putSuccessCount + ' message(s)')
You can store the correlation id into JMeter Variables like:
vars.putObject('correlationId', message.correlationId)
where vars stands for JMeterVariables class instance, see Top 8 JMeter Java Classes You Should Be Using with Groovy article for more details.
then in order to retrieve a particular message you need to do something like:
def queueOptions = new MQGetMessageOptions()
queueOptions.options = CMQC.MQGMO_WAIT | CMQC.MQGMO_CONVERT
queueOptions.matchOptions = CMQC.MQMO_MATCH_CORREL_ID
def response = new MQMessage()
response.correlationId = vars.getObject('correlationId')
queue.get(response, queueOptions)
More information: Getting a particular message
I'm having trouble updating the notes of contacts through Googles People API. I used some code from a previous stackoverflow answer, but it doesn't seem to work anymore. Below is the function I'm using. I'm attempting to change the notes of a particular contact to "changed bio xyz".
What am I doing wrong? The api does read a listing of the contacts, but I haven't been able to successfully write yet.
Thanks and please let me know if I can make this question more clear
results = service.people().connections().list(
resourceName='people/me',
pageSize=1500,
personFields='names,emailAddresses,phoneNumbers,biographies').execute()
connections = results.get('connections', [])
aContact = service.people().get(
resourceName = 'people/c1589313158061148817',
personFields = 'biographies' ).execute()
notesNames = aContact['biographies'][0]
notesNames['value'] = 'changed bio xyz'
result = service.people().updateContact(
resourceName = 'people/c1589313158061148817',
body = aContact,
updatePersonFields = 'biographies'
).execute()
I figured it out. The update goes in the body section, and it needs to follow a dictionary format
aContact = service.people().get(
resourceName = 'people/c36943406266964946',
personFields = 'names,nicknames'
).execute()
print ('this is acontact', aContact)
NickNames = aContact['nicknames'][0]
NickNames['value'] = 'newNickName'
aContact['nicknames'] = NickNames
result = service.people().updateContact(
resourceName = 'people/c36943406266964946',
body = aContact,
updatePersonFields = 'nicknames'
).execute()
In the soap response below (from SoapUI), under the parent SearchForReservationResponse tag, I am trying to pull out the values of Reservation id, Restaurant id and Location id with Savon 2.
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<SearchForReservationResponse xmlns="http://schemas.livebookings.net/OneFormat/Aggregator/Internal/1/0/">
<Reservation id="34639536" status="Confirmed">
<DiningDateAndTime>2015-07-01T17:00:00</DiningDateAndTime>
<Restaurant id="25200">
<Name>Eat Food - UK Demo Website - Bookatable.com</Name>
<Location id="35839">
<Name>Bar</Name>
</Location>
</Restaurant>
<Size>2</Size>
<Created>2015-07-01T13:22:17.41</Created>
<SessionId>DINNER</SessionId>
<FirstName>John</FirstName>
<LastName>Smith</LastName>
<ConfirmationNumber>JWRW5HR5</ConfirmationNumber>
<AllowedToCancelOnline>true</AllowedToCancelOnline>
<RestaurantPhoneNumber type="Main">+44 7951300529</RestaurantPhoneNumber>
</Reservation>
</SearchForReservationResponse>
</soap:Body>
</soap:Envelope>
Below is my attempt for trying to access Reservation id. After a lot of googling I found that the new Savon 2 syntax uses #attrib, but I keep getting errors as I think I am not using this Ruby nested hash syntax correctly - I find it very confusing and am fairly new to Ruby. If you could help me out here it would be much appreciated!
require 'savon'
class SearchReservation
attr_reader :reservation_id
def client
client = Savon.client(wsdl: "http://example-wsdl-url", follow_redirects: :follow_redirects)
end
def main_method(confirm_number, email)
message = {'ConfirmationNumber' => "JWRW5HR5", 'EMail' => "jon#" }
response = client.call(:search_for_reservation, message: message)
data = response.body(:search_for_reservation_response => { #attrib => {:reservation => :id} })
if data
#reservation_id = data[:id]
end
end
end
search = SearchReservation.new
puts search.main_method("JWRW5HR5", "jon#")
N.B. the email value jon# doesn't have to be a valid email address (used just for testing purposes) - it returns a valid response in SoapUI.
My last syntax error trace in the terminal/console:
/~/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/savon-2.11.1/lib/savon/response.rb:36:in `body': wrong number of arguments (1 for 0) (ArgumentError)
from search.rb:13:in `main_method'
from search.rb:22:in `<main>'
My final solution pulling out all the values I need. Of note: even though dining_date_and_time was presented as xml when putting response.body, when it is extracted using #dining_date_and_time = data[:dining_date_and_time] the date and time values get printed cleanly. This is key once porting to a fully-fledged Rails app.
Despite all the discussion online about attributes, ids within an xml tag can be pulled by just ensuring you are far enough down the "tree" (ie. location id falls under location tag) and then specifying the key: in this case the api displays it as :#id for each nested case.
N.B, this only returns the last value called each time in console. But all values should be pulled in views once integrated into Rails. (Hopefully!)
require 'savon'
class SearchClass
def client
client = Savon.client(wsdl: "http://wsdl-example-url", follow_redirects: :follow_redirects)
end
def return_data(confirm_number, email)
message = {'ConfirmationNumber' => confirm_number, 'EMail' => email }
response = client.call(:search_for_reservation, message: message)
data = response.to_hash[:search_for_reservation_response][:reservation]
#reservation_id = data[:#id]
#dining_date_and_time = data[:dining_date_and_time]
#size = data[:size]
#session_id = data[:session_id]
#first_name = data[:first_name]
#last_name = data[:last_name]
#confirm_number = data[:confirmation_number]
#allowed_to_cancel_online = data[:allowed_to_cancel_online]
#restaurant_phone_number = data[:restaurant_phone_number]
data2 = response.to_hash[:search_for_reservation_response][:reservation][:restaurant]
#restaurant_id = data2[:#id]
#restaurant_name = data2[:name]
data3 = response.to_hash[:search_for_reservation_response][:reservation][:restaurant][:location]
#location_id = data3[:#id]
#location_name = data3[:name]
end
end
search = SearchClass.new
puts search.return_data("JWRW5HR5", "jon#")