Is there any way to change the order of arguments? - discord.js

I'm working on a command that searches maps for the game osu! on the site bloodcat.com and I made a way to filter the maps with:
.split('status=ranked').join('&c=b&s=1&m=&g=&l=')
.split('status=approved').join('&c=b&s=2&m=&g=&l=')
.split('status=qualified').join('&c=b&s=3&m=&g=&l=')
.split('status=loved').join('&c=b&s=4&m=&g=&l=')
.split('status=unranked').join('&c=b&s=0&m=&g=&l=')
.split('status=graveyarded').join('&c=b&s=0&m=&g=&l=');
Now someone can do !search 'map name' status=unranked and that would look for https://bloodcat.com/osu/?mod=json&q='map name'&c=b&s=0&m=&g=&l= but if someone does for example !search status=unranked 'map name' that doesn't work is there any way.
Can I make the status=unranked at the end even if the user doesn't put it in the end in the command?

I would do it like this: first, check if the string of arguments starts with status=. If so, you'll need to switch them, otherwise, it should work as it's doing now.
In order to switch those, I would split the string with spaces, remove the first argument (status=*), rejoin that with spaces and add the removed part:
function getQueryURL(argStr = "") { // argStr should be like "'map name' status=unranked" OR "status=unranked 'map name'"
if (argStr.startsWith('status=')) {
let arr = argStr.split(' ');
let removed = arr.shift();
argStr = arr.join(' ').trim() + removed.trim();
}
let res = argStr.split('status=ranked').join('&c=b&s=1&m=&g=&l=')
.split('status=approved').join('&c=b&s=2&m=&g=&l=')
.split('status=qualified').join('&c=b&s=3&m=&g=&l=')
.split('status=loved').join('&c=b&s=4&m=&g=&l=')
.split('status=unranked').join('&c=b&s=0&m=&g=&l=')
.split('status=graveyarded').join('&c=b&s=0&m=&g=&l=');
return "https://bloodcat.com/osu/?mod=json&q=" + res;
}

Related

Laravel 7: Showing error while passing multiple variable in str_replace

I'm facing error while passing multiple variable in str_replace function.
Error: Argument 1 passed to Xenon\LaravelBDSms\SMS::shoot() must be of the type string, null given, called in
Message Body:
Hello #name#,
Total Amount Purchased : #total#
Previous Due: #previous_due#
Deposit: #deposit#
Total Due: #total_due#
Controller:
$id = 1;
$sms_settings = SmsSetting::findOrFail($id);
if($sms_settings->order_create == 1){
$name = $request->name;
$previous_due = $customer->due;
$deposit = $request->deposit;
$total = $request->total;
$total_due = $request->total_due;
$msgs = $sms_settings->order_create_sms;
$msg = str_replace(array('#name#', '#total#','#previous_due#','#deposit#','#total_due#'), array($name,$previous_due, $deposit, $total, $total_due), $msgs);
$send= SMS::shoot($request->mobile, $msg);
}
Shoot Function:
public function shoot(string $number, string $text)
{
$this->sender->setMobile($number);
$this->sender->setMessage($text);
return $this->sender->send();
}
Here I'm using a Laravel Package for sending SMS to mobile number. How can I pass multiple variable in str_replace?
$request->mobile is null, confirm if you are passing the same in the request. Thats why the error.
Also use $request->validated('mobile'), that is safer.
str_replace seems to be fine. Take a look at Example, but Look at examples again, it might break if characters are overlapping with other arguments
I think the variable $msgs = $sms_settings->order_create_sms; contain empty that's why str_replace couldn't replace the data that you given so
$msg = str_replace(array('#name#', '#total#','#previous_due#','#deposit#','#total_due#'), array($name,$previous_due, $deposit, $total, $total_due), $msgs); , will return null.
I recommend checking $msgs again.
$msgs = $sms_settings->order_create_sms;
Make sure $msgs is not null place is_null($msgs) condition before feeding to str_replace
check more about str_replace: https://www.php.net/manual/en/function.str-replace.php

Return Stringbuilder when using variable name to create string builder

trying to return string builder in a loop. is this workable.. I am collecting a list with each(), then appending 'it' to "scriptBldr_" to create a different object name each time to hold the string. then I collect the object names in a list. And trying to return using a for loop for each object name. But it's failing.
List.each {
String builderstring = "scriptBldr_" + it.replaceAll (/"/, '')
StringBuilder $builderstring = StringBuilder.newInstance()
if (ValidUDA == "Region") {
$builderstring <<"""
XYZCode
"""
StringBuilders.add(builderstring)
}
}
for(item in StringBuilders)
{
return item
}
I guess the following code does what you intended to code:
def myList = ['Hello "World"', 'asb"r"sd']
def ValidUDA = "Region"
def builders = [:]
myList.each {
String builderstring = "scriptBldr_" + it.replaceAll (/"/, '')
builders[builderstring] = StringBuilder.newInstance()
if (ValidUDA == "Region") {
builders[builderstring] <<"""
XYZCode
"""
}
}
return builders
A return statement will immediatly return from the method and hence will exit the loop and only called once. So, I guess, what you wanted to achieve is to return a list of StrinngBuilders.
some hints:
it is unusual in Groovy to start a variable with $ and you can run into problems with such a naming
when asking a question on SO, try to come up with a working example. As you can see, you example was missing some definitions
Update: as you've stated in you comment that you tryed to create dynamic variable names, I've updated the code to use maps. The returned map now contains the StringBuilders together with their names.

Best way to get arguments from string by user for chat bot

I need to accept 2 arguments: first is time argument for example "1m", "2h 42m", "1d 23h 3s", second is text. I thought I can just convert input string to array and split it into 2 array using regex maybe, first with "d", "h", "m" and "s", second everything else and convert in back to string. but then I realize I'll need 3rd argument which gonna be optional target channel (dm or current channel, where command been executed), and also what if user want to include 1m in his text (it's reminder command)
The easiest way to do this is to have the user seperate each argument by a comma. Although this creates the issue where the user can't user a comma in their text part. So if that isn't an option, another way to do it is to get the message content and start by stripping parts of it away. You begin by grabbing the time portion with a regex. Then you look for channel mentions and strip those away. What you're left with should solely be the text.
Below is some (non-tested) code which could lead you in the right direction. Give it a try and let me know if you have any problems
let msg = {
content: "1d 3h 45m 52s I feel like 4h would be to long <#222079895583457280>",
mentions: {
channels: ['<#222079895583457280>']
}
};
// Mocked Message object for testing purpose
let messageObject = {
mentions: {
CHANNELS_PATTERN: /<#([0-9]+)>/g
}
}
function handleCommand (message) {
let content = message.content;
let timeParts = content.match(/^(([0-9])+[dhms] )+/g);
let timePart = '';
if (timeParts.length) {
// Get only the first match. We don't care about others
timePart = timeParts[0];
// Removes the time part from the content
content = content.replace(timePart, '');
}
// Get all the (possible) channel mentions
let channels = message.mentions.channels;
let channel = undefined;
// Check if there have been channel mentions
if (channels.length) {
channel = channels[0];
// Remove each channel mention from the message content
let channelMentions = content.match(messageObject.mentions.CHANNELS_PATTERN);
channelMentions.forEach((mention) => {
content = content.replace(mention, '');
})
}
console.log('Timepart:', timePart);
console.log('Channel:', channel, '(Using Discord JS this will return a valid channel to do stuff with)');
console.log('Remaining text:', content);
}
handleCommand(msg);
For the messageObject.mentions.CHANNEL_PATTERN look at this reference

Swift 4 Replace word within String

The setup: A UITextField and a Tableview with suggested users
I try to have the following result:
I want users to be able to link other users.
Its working fine as long as I search with my last word in the array
let caption = captionTextView.text
let words = caption?.components(separatedBy: .whitespacesAndNewlines)
guard let searchingWord = words?.last else {return}
if searchingWord.hasPrefix("#") {
self.indicator.startAnimating()
let search = searchingWord.trimmingCharacters(in: CharacterSet.punctuationCharacters).lowercased()
}
But in case a user wants to adjust a username in the middle or at least not at the end of the array, the searching functions doesn't work properly as it still searches with the last word in the array
Example:
"Hey how are you #Lisa #Marcel #Thomas"
In case a user wants to change "#Lisa" to "#Lisbeth" the search function will search with Thomas as its the last word in the array
I wasn't able to get the word I am working at, only last and first words in the array, however I am able to get the current cursor location with
let cursor = captionTextView.cursorOffset!
which is an extension.
So how do I get the word I am working at up until the next "#" to the left und the next blank space to the right? Thanks in advance!
Maybe try something like this:
if let selectedRange = textview.selectedTextRange {
let cursorOffset = textview.offset(from: textview.beginningOfDocument, to: selectedRange.start)
let text = textview.text
let substring = text?.prefix(cursorOffset)
let editedWord = substring?.split(separator: "#")
}
(written on a phone, and untested)
One solution is Regular Expression
let string = "Hey how are you #Lisa #Marcel #Thomas"
let searchingWord = "Lisa"
let replacingWord = "Lisbeth"
let pattern = "#\(searchingWord)\\s"
string.replacingOccurrences(of: pattern, with: "#\(replacingWord) ", options: .regularExpression)
The pattern searches for # followed by the searching word followed by a whitespace character.
Since you say things are working the way you want if the last word is the one that has a username in it you just need to loop over all the words. Depending on your needs you may need to keep track of the usernames that were in the text before to save you from searching for the same user multiple times, but an array of used usernames should sort that for you.
Also, unless you want to prevent users from having underscores and the such in their names you should tweak the way in which you remove the # symbol as well.
guard let words = captionTextView.text?.components(separatedBy: .whitespacesAndNewlines) else { return }
for word in words where word.hasPrefix("#") {
self.indicator.startAnimating()
let search = word.replacingOccurrences(of: "#", with: "").lowercased()
}
Sticking the above code into a playground that uses the sample string you supplied in place of captionTextView.text? and printing search each time yielded…
lisa
marcel
thomas

prepare mentions and hashtags to parse array object

this is my first post and question. Here is what i'm doing to collect hashtags from UIText Field. It's working but I think this is not the correct way to do this. Any ideas? I need an array of hashtags as words.
Need to collect these type of tags: "Hey, this is my first photo!#photo #hashtag #daily:)
Here is my code;
// Prepare words
let words:[String] = titleTxt.text!.componentsSeparatedByCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
self.taggyArray.removeAll(keepCapacity: false)
// define tagged word if #
for var word in words {
if word.hasPrefix("#") {
// cut symbold
word = word.stringByTrimmingCharactersInSet(NSCharacterSet.punctuationCharacterSet())
word = word.stringByTrimmingCharactersInSet(NSCharacterSet.symbolCharacterSet())
// now prepare adjacent tags
let tags:[String] = word.componentsSeparatedByCharactersInSet(NSCharacterSet.init(charactersInString: "#"))
for tag in tags {
taggyArray += [tag]
}
}
}
And save to server
object["hashtags"] = taggyArray
Is it possible to work this just with one regex seperation? Thank you,
Try this.
let matches = regex.matchesInString("(\#\w+)", ""Hey, this is my first photo!#photo #hashtag #daily:)")
println(matches)

Resources