args.join is not a function - discord

With my discord bot I am working on a weather command that shows weather on the specified country but when trying to run my command I'm getting this error: TypeError: args.join is not a function Any fix?
My code:
const weather = require('weather-js');
const discord = require('discord.js')
module.exports = {
name: "weather",
description: "Get the weather of anywhere",
category: "info",
usage: "weather <>",
run: ( message, args, client) => {
weather.find({search: args.join(" "), degreeType: 'F'}, function(err, result) {
try {
const embed = new MessageEmbed()
.setTitle(`Weather - ${result[0].location.name}`)
.setColor("#ff2050")
.setDescription("Temperature units can may be differ some time")
.addField("Temperature", `${result[0].current.temperature} Celcius`, true)
.addField("Sky Text", result[0].current.skytext, true)
.addField("Humidity", result[0].current.humidity, true)
.addField("Wind Speed", result[0].current.windspeed, true)
.addField("Observation Time", result[0].current.observationtime, true)
.addField("Wind Display", result[0].current.winddisplay, true)
.setThumbnail(result[0].current.imageUrl);
message.channel.send(embed)
} catch(err) {
return message.channel.send("Unable To Get the data of Given location")
}
});
}
}
I've also tried if (args[0].join... but that doesn't work.

I may be wrong but you have to split the args args.split(" ") before you can join them.
The args returns a string Hello World!
If you were to use args.split(" ") you could do const textSplit = args.split(" ")
It would then return ["Hello", "World!"] as an array
You could THEN use textSplit.join(" ") to add all strings in the array together with with a space.
It would return a string that says "Hello World!"
You could then use textSplit[0] to grab specific text from the array. The 0 position is the word Hello, the 1 position is the word World! and so on. Arrays start from the number 0.
[
"Hello", (0)
"World!" (1)
]
Hope this helps

Related

Append result of CloudKit into array in swift

i declare the contact variable as an empty string array
var contact = [String] ()
then I made a query to output the results from CloudKit, when I accessed the controller once, var contact succeeded in adding an array
let predicate = NSPredicate(value: true)
let query = CKQuery(recordType: "Note", predicate: predicate)
database.perform(query, inZoneWith: nil) { (record, error) in
for record: CKRecord in record! {
let name = record.value(forKeyPath: "content") as! String
print ("There is a note \"\(name)\"")
self.contact.append(name)
}
}
self.contact.append (name)
print ("There is a note \" \ (name) \ "")
but when accessing for the second time, the var contact becomes empty again
print ("check all array append \ (contact)")
Succes append firstime access the controller
Failed append secondtime access the controller
i use variable contact in other function
func sendSOS() {
if canSendText() {
//compese message with google link
let googleLink = "https://www.google.com/maps/place/" + String(myLatitude!) + "+" + String(myLongtitude!)
let SMStext = "EMERGENCY!!, Tolong Bantu saya di lokasi Latitude: " + String(myLatitude!) + "\n Longtitude: " + String(myLongtitude!) + " " + googleLink
let messsageCompose = MFMessageComposeViewController()
messsageCompose.messageComposeDelegate = self
messsageCompose.recipients = contact;
messsageCompose.body = SMStext
present(messsageCompose, animated: true, completion: nil)
}else{
// create the alert
let alert = UIAlertController(title: "No SMS available.", message: "Please find a better location and try again!", preferredStyle: UIAlertController.Style.alert)
// add an action (button)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil))
// show the alert
self.present(alert, animated: true, completion: nil)
return
}
}
It's difficult to determine what's going on because you're leaving out how the contact array is initialized relative to your CKQuery.
The database.perform line looks a little suspicious. I'm pretty sure that returns an array of CKRecords so you should have:
database.perform(query, inZoneWith: nil) { records, error in
//records is an optional array
if let records = records{
for record in records{
//You might have to parse record.values to get its key/value pairs
let name = record["content"] as? String ?? "No Name"
print("There is a note: \(name)")
//:::
self.contact.append(name)
}
}
}
As a side note, I recommend using CKQueryOperation for all queries (docs). It's a cleaner way to manage data flowing from CloudKit.

How to set multiple field in Firestore document at once in swift

I'm trying to write two arrays of a custom object to Firestore document.
When I execute the program it only write the last one from the array.
The custom class is codable and encodable.
This is the function that execute the write function to Firestore:
func setShiftConstraints<ShiftConst: Codable>(employeeId: String, for encodeObject: ShiftConst, completion: #escaping (Bool)->()){
do{
let json = try encodeObject.toJson(excluding: [], photoString: nil)
let date = Date().toFormat(DateFormats.format3.rawValue)
self.db.batch().setData([date : json], forDocument: self.reference(to: .shifts).document(employeeId), merge: false).commit()
print("Shift uploaded!")
completion(true)
}catch let err{
print(err.localizedDescription)
completion(false)
}
}
And this is the function that get called when the user is submitting his arguments.
func sendShiftsDataToCloud(){
let group = DispatchGroup()
var returned = true
shiftConsts[0].shiftType = ShiftType(rawValue: self.shift1SegmentControl.selectedSegmentIndex)!
shiftConsts[1].shiftType = ShiftType(rawValue: self.shift2SegmentControl.selectedSegmentIndex)!
for shift in self.shiftConsts{
group.enter()
shift.date = Day().convertDateFormat(from: .format1, to: .format9, date: shift.date)
self.service.setShiftConstraints(employeeId: self.service.currentUid!, for: shift) { (finish) in
if !finish{
returned = false
}
}
group.leave()
}
group.notify(queue: .main) {
if returned{
print("finish")
Alert.showAlert(title: "Success!", text: "", type: .success)
}else{
print("error")
Alert.showAlert(title: "Error!", text: "Please try again.", type: .error)
}
}
}
the result is one array instead of two:

Sending an email with a loop as body in Swift

I would like to send an email with different steps and values depending on what the user has edited on an image. For that, I'm using UserDefaults to save values.
Then I have the next code into an UIAlertController:
alert.addAction(UIAlertAction(title: "Send", style: .default)
{ action -> Void in
//i is the last step register
let nombre = alert.textFields![0]
for n in 1...self.i {
print("Step \(n): \(self.filterUserDefaults.string(forKey: "Step_\(n)")!)")
}
let filters = [
"Brillo",
"Exposicion",
"Contraste",
"Saturacion",
"Saturacion_color",
"Temperatura",
"Blanco_Negro",
"HUE",
"Tintado_Rojo",
"Tintado_Rosa",
"Tintado_Naranja",
"Tintado_Amarillo",
"Tintado_Purpura",
"Tintado_Verde",
"Tintado_Azul",
"Tintado_Marron",
"Tintado_Gris"]
for filter in filters {
print("\(filter) = \(self.filterUserDefaults.float(forKey: filter).roundTo(places: 3))")
}
self.sendMail(filtro: nombre.text!, body: "XXXX")
})
present(alert, animated: true)
}
func sendMail(filtro: String, body: String) {
if MFMailComposeViewController.canSendMail() {
let mail = MFMailComposeViewController()
mail.mailComposeDelegate = self
mail.setToRecipients(["blablabla#gmail.com"])
mail.setSubject("Filtro \(filtro)")
mail.setMessageBody(body, isHTML: true)
present(mail, animated: true)
} else {
print("Error presenting email app.")
}
}
So printing is working as I expect but the problem is to put these prints into the body of sendMail function...
I tried:
var steps: [String]?
for n in 1...self.i {
steps = ["Step \(n): \(self.filterUserDefaults.string(forKey: "Step_\(n)")!)"]
}
.
.
.
self.sendMail(filtro: nombre.text!, body: steps!.joined(separator: "\n"))
But only the last step is written into the body's email and not the array...
Please, can anyone help me?
Thank you in advance!
u can try out following code
var steps: String = ""
for n in 1...self.i {
steps += "Step \(n): \(self.filterUserDefaults.string(forKey: "Step_\(n)")!)"
}
You are almost there, you need to initialise your array variable and use append
var steps = [String]()
for n in 1...self.i {
steps.append("Step \(n): \(self.filterUserDefaults.string(forKey: "Step_\(n)")!)")
}
...
self.sendMail(filtro: nombre.text!, body: steps.joined(separator: "\n"))

Search for multiple words ignoring the order in Swift 5

In my app I built a SearchBar which, for a single word, works perfectly fine.
import Foundation
class Clinic {
var id = ""
var name = ""
var address = ""
var specialty1 = ""
var specialty2 = ""
}
In my textDidChange I have
var clinics: [Clinic] = [] // Clinics Data Structure
var clinicsSearch: [Clinic] = [] // Filtered Clinics
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
// works for one word (either in name or specialty1 or specialty2)
clinicsSearch = clinics.filter { $0.name.lowercased().contains(searchText.lowercased()) ||
$0.specialty1.lowercased().contains(searchText.lowercased()) ||
$0.specialty2.lowercased().contains(searchText.lowercased())
}
searching = true
tableView.reloadData()
}
With the func above, if I start typing something, it will bring all results that meet the criteria (if the typed word is found in the Name OR Specialty1 OR Specialty2).
I now started to look to improve my code and want to implement an option where the user could type words in different order like: Name SPACE specialty(1or2), specialty(1or2) SPACE Name etc and the app would search all 3 fields for all typed words. Order independent.
I found here something very similar to what I'm looking for but I couldn't ask there as I'm below 50 reputation
Search for multiple words ignoring the order in Swift
The main difference from the solution presented there is that they use basic a array in the example
let filterArray = ["Big green bubble", "Red bubble", "A bubble in green", "Small green bubble", "This bubble is green"]
That is different from mine, that is based in the Class Clinic above. I tried to adapt their code to my case as below
let textString = searchText.lowercased()
let words = textString.components(separatedBy: " ")
clinicsSearch = clinics.map { $0.name.lowercased() }.filter { string in words.allSatisfy { string.components(separatedBy: " ").contains($0) } }
But I get several errors like Value of type 'Clinic' has no member 'lowercased' or Value of type 'Clinic' has no member 'components' (there are others as well) that I don't know how to fix.
Any help is greatly appreciated.
Thanks
You can try
let searArr = searchText.lowercased().components(separatedBy: " ")
clinicsSearch = clinics.filter { item in
let res = searArr.filter { item.name.lowercased().contains($0) ||
item.specialty1.lowercased().contains($0) ||
item.specialty2.lowercased().contains($0)
}
return !res.isEmpty
}
It could be better to do
let searArr = searchText.lowercased().components(separatedBy: " ")
clinicsSearch = clinics.filter { item in
let lowName = item.name.lowercased()
let lowSp1 = item.specialty1.lowercased()
let lowSp2 = item.specialty2.lowercased()
let res = searArr.filter {
lowName.contains($0) ||
lowSp1.contains($0) ||
lowSp2.contains($0)
}
return !res.isEmpty
}

How to add a struct to an array of structs in Go

In golang I'm trying to make an array of messages, and the ability to easily add a new "object" to the array.
type Message struct {
Name string
Content string
}
var Messages = []Message{
{
Name: "Alice",
Content: "Hello Universe",
},{
Name: "Bob",
Content: "Hello World",
},
}
func addMessage(m string) {
var msg = new(Message)
msg.Name = "Carol"
msg.Content = m
Messages = append(Messages, msg)
}
When building I get an error that says:
cannot use msg (type *Message) as type Message in append
Why is append() not working (as I might expect from JavaScript's array.concat()), or is new() not working?
Any other tips on how to improve this code are welcome since I'm obviously new to Go.
Change these 3 lines
var msg = new(Message)
msg.Name = "Carol"
msg.Content = m
to
msg := Message{
Name: "Carol",
Content: m,
}
and everything should work. new creates a pointer to Message. Your slice is not a slice of Message pointers, but a slice of Messages.
In your code, Messages is a slice of Message type, and you are trying to append a pointer of Message type (*Message) to it.
You can fix your program by doing the following:
func addMessage(m string) {
var msg = new(Message) // return a pointer to msg (type *msg)
msg.Name = "Carol"
msg.Content = m
Messages = append(Messages, *msg) // use the value pointed by msg
}
Alternatively, you can declare Messages as a slice of *Message:
var Messages = []*Message{
&Message{ // Now each entry must be an address to a Message struct
Name: "Alice",
Content: "Hello Universe",
},
&Message{
Name: "Bob",
Content: "Hello World",
},
}
In above case, addMessage wouldn't require any changes. But you'll have to modify Messages access everywhere else.

Resources