mIRC bot - copy/paste lines in 2 channels - irc

I’m a noob in mirc scripting, and I need some help.
there’s 2 irc channels. let’s call then #channel1 and #channel2;
There’s 2 bots. One is mine, let’s call him “mybot” (my bot is in both channels). The other bot is from a third person, let’s call him “otherBot”;
What I need is… let me make an example to better explain.
a) in #channel1 some user type:
[14:38:48] <#someuser> !user xpto
At this time, “mybot” is in both channels. he reads the command “!user*” and copy/paste it in #channel2, where the “otherBot” will recognize the command “!user*” and will paste some information about this command.
b) so, in #channel2 it will append something like:
[14:38:50] <# mybot > !user xpto
[14:38:52] <# otherBot > User name is xpto and he likes popatos.
Now I want that “mybot” reads the information provided by the “otherBot” and then paste it on #channel1
c) so, in #channel1:
[14:38:54] <# mybot > User name is xpto and he likes popatos.
So far I have the fowling code in my remote:
on *:TEXT:!user*:#channel1 {
/msg # channel2 $1-
}
on *:TEXT:User name*:#channel2 {
if $address($nick,2) == *!*#otherBot.users.gameea {
/msg # channel1 $1-
}
}
This works fine, but have a problem: if someone else ( not “mybot” ) type “!user kakaka” in #channel2, “mybot” will also copy/paste the information provided by the “otherBot” and then paste it on #channel1. And I only want that “mybot” copy/paste only the information that “mybot” ask to “otherBot”.

A very simple (but not a particularly nice) way of doing this could be to set a global variable when someone types !user in #channel1, and check whether or not this is set in the other part which is listening on #channel2. For example:
on *:TEXT:!user *:#channel1: {
set %repeatUser 1
msg channel2 $1-
}
on *:TEXT:User name*:#channel2: {
if ($address($nick,2) == *!*#otherBot.users.gameea && %repeatUser == 1) {
unset %repeatUser
msg #channel1 $1-
}
}
This isn't a perfect solution, since if the bot says something else between the time it takes for the script to send '!user' to the other channel and for the bot to respond, then it will print out that reply instead of the one for your request, but this is only relevant if #channel2 is ridiculously busy, otherbot is very laggy, or it just so happens that both your bot and someone else type !user on #channel2 within a fraction of a second of eachother.

Related

MIKMIDI: writing events on a track produces a warning

I'm trying to write a program to shift the key of a midi file. Basically, I just need to shift every note event by a given amount and live the rest unchanged. I found it easy to use MIKMIDI to read, parse, modify and write back the stream.
Unfortunately, I have a problem that I'm unable to solve. I've a loop in which I select the note events and add/subtract the desired shift value, but when I append the event in the output track I get a message from the MIKMIDI library:
"Warning: attempted to insert a NULL event".
The code I wrote is the following:
for event in inputTrack.events {
if event.eventType == .midiNoteMessage {
var tmpData = event.data
if (event.data[0] != 9) { // skip percussion channel
tmpData[1] = event.data[1] - shift
}
let outEvent = MIKMIDIEvent(timeStamp: event.timeStamp, midiEventType: .midiNoteMessage, data: tmpData)!
outputSeq.tracks[i].events.append(outEvent)
}
else {
outSeq.tracks[i].events.append(event)
}
}
BTW, the code works perfectly (the midi file is plays as expected), it is just that it takes minutes to execute in debugging mode due to the infinite sequence of warning messages printed in the debug screen.
Thanks!

How to differentiate as abbreviation for voice response in dialog flow

I have integrated my dialogflow agent with google assistant. There is a welcome intent that will ask you to choose any of the option
Choose any of the sports
1. NBA
2. NHL
3. FIH
It reads the response with ever individual words(as an abbreviation). But when I produce the same in response from webhook, it is not reading the response with individual words(or not considering the response as abbreviation) and reads together. How can I achieve this? Am I missing something in the response?
You likely want to make sure you're sending back SSML in your response, rather than sending back text and letting it convert it to speech, and specifically marking the abbreviations using the <say-as> tag and telling it to interpret the contents as characters.
So you might send it back as something like:
<speak>
Are you interested in learning more about
the <say-as interpret-as="characters">NBA</say-as>,
the <say-as interpret-as="characters">NHL</say-as>
or the <say-as interpret-as="characters">FIH</say-as>?
</speak>
The little pronunciation differences with and without SSML are serious problems. I stick in a speak /speak for everything. Also a unique number I like and a test hook to have speech 'count' or not so there is a way to test things. Also a hook so an intent is triggered for 'repeat that please' :
Point is to use sayUsual for everything ordinary.
// Mostly SSML start char kit as globals
const startSp = "<speak>", endSp = "</speak>";
// Handle "Can you repeat that ?" well
var vfSpokenByMe = "";
// VF near globals what was said, etc
var repeatPossible = {}; repeatPossible.vf = ""; repeatPossible.n = 0;
// An answer from this app to the human in text
function absorbMachineVf( intentNumber, aKind, aStatement )
{
// Numbers reserved for 'repeats'
if( intentNumber > 9000 ) { return; }
// Machine to say this, a number for intents too
repeatPossible.vf = aStatement; repeatPossible.n = intentNumber;
}
// Usual way to say a thing
function sayUsual( n, speechAgent, somethingToSay )
{
// Work with an answer of any sort
absorbMachineVf( n, 'usual', somethingToSay );
// Sometimes we are just pretending, so
if( !testingNow )
{ speechAgent.add( startSp + somethingToSay + endSp ); }
// Make what we said as an answer available 'for sure' to rest of code
vfSpokenByMe = somethingToSay; // Even in simulation
}

Mirc script to find exact match in customer list

I am using this to find customer name in text file. Names are each on a separate line. I need to find exact name. If searching for Nick specifically it should find Nick only but my code will say found even if only Nickolson is in te list.
On*:text:*!Customer*:#: {
if ($read(system\Customer.txt,$2)) {
.msg $chan $2 Customer found in list! | halt }
else { .msg $chan 4 $2 Customer not found in list. | halt }
}
You have to loop through every matching line and see if the line is an exact match
Something like this
On*:text:*!Custodsddmer*:#: {
var %nick
; loop over all lines that contains nick
while ($read(customer.txt, nw, *nick*, $calc($readn + 1))) {
; check if the line is an exact match
if ($v1 == nick) {
%nick = $v1
; stop the loop because a result is found
break;
}
}
if (%nick == $null) {
.msg $chan 4 $2 Customer not found in list.
}
else{
.msg $chan $2 Customer found in list!
}
You can find more here: https://en.wikichip.org/wiki/mirc/text_files#Iterating_Over_Matches
If you're looking for exact match in a new line separate list, then you can use the 'w' switch without using wildcard '*' character.
From mIRC documentation
$read(filename, [ntswrp], [matchtext], [N])
Scans the file info.txt for a line beginning with the word mirc and
returns the text following the match value. //echo $read(help.txt, w,
*help*)
Because we don't want the wildcard matching, but a exact match, we would use:
$read(customers.txt, w, Nick)
Complete Code:
ON *:TEXT:!Customer *:#: {
var %foundInTheList = $read(system\Customer.txt, w, $2)
if (%foundInTheList) {
.msg # $2 Customer found in list!
}
else {
.msg 4 # $2 Customer not found in list.
}
}
Few remarks on Original code
Halting
halt should only use when you forcibly want to stop any future processing to take place. In most cases, you can avoid it, by writing you code flow in a way it will behave like that without explicitly using halting.
It will also resolve new problems that may arise, in case you will want to add new code, but you will wonder why it isn't executing.. because of the darn now forgotten halt command.
This will also improve you debugging, in the case it will not make you wonder on another flow exit, without you knowing.
Readability
if (..) {
.... }
else { .. }
When considering many lines of codes inside the first { } it will make it hard to notice the else (or elseif) because mIRC remote parser will put on the same identification as the else line also the line above it, which contains the closing } code. You should almost always few extra code in case of readability, especially which it costs new nothing!, as i remember new lines are free of charge.
So be sure the to have the rule of thump of every command in a new line. (that includes the closing bracket)
Matching Text
On*:text:*!Customer*:#: {
The above code has critical problem, and bug.
Critical: Will not work, because on*:text contains no space between on and *:text
Bug: !Customer will match EVERYTHING-BEFORE!customerANDAFTER <NICK>, which is clearly not desired behavior. What you want is :!Customer *: will only match if the first word was !customer and you must enter at least another text, because I've used [SPACE]*.

Stuck trying to write script to register username with tilte

Working on a bot script to lookup a username on join and see if it's be regiester with a title for the channel I run. Like if my name is Ravenna. I want the bot to check if I've registered the title Mistress with the username Ravenna.
I'm extremely stuck on how to go about this, researching things haven't brought me closer to a solution
so far all I've figured out I want is
on *:JOIN:#channel {
.msg $chan $nick take time to register with me; a pm will be sent to you soon
}
Any help or a source where I can figure out how to write and read files or the snippet code I need would be appericated
I think it's the best to use ini files for this. You should have a look at this: http://en.wikichip.org/wiki/mirc/ini_files and for more on http://en.wikichip.org/wiki/mirc.
For example you have a title called Mistress, your titles.ini file would look like this:
[mistress]
Ravenna=true
[mister]
Denny=true
To read a value you can use: $readini(titles.ini,n,mistress,$nick)
And to check the value you can do:
on *:join:#channel: {
if ($readini(titles.ini,n,mistress,$nick)) {
; code here for mistress
}
elseif ($readini(titles.ini,n,mister,$nick)) {
; code here for mister
}
elseif ($readini(titles.ini,n,TITLE,$nick)) {
; code here for another title
}
else {
; code here when no title
}
}
This way you must manually add a title in your titles.ini file. So if you want to add another title you should add [TITLE] on a new line in your ini file. If you have more questions you can ask here.
If you want to register someone with a title you could make a simple on text event and add a name to the ini file with writeini titles.ini TITLE $nick true
on *:join:#Tristram_Halls: {
if ($readini(titles.ini,n,mistress,$nick)) {
.describe $chan looks up and sees Mistress $nick. "Greetings Mistress."
}
else {
.msg $chan Greetings $nick I have no record of what you are. Please take the time to register that info with me
.msg $chan $nick Please choose from one of the following titles: !Mistress
}
}
on *:text:!Mistress:#:{
/writeini [-n] titles.ini mistress $nick true
}
just testing a short code for mirc title registration. At this point nobody is in the ini file, and I've add the title [mistress] but when anybody joins the channel the bot does this rather than c
Testbot looks up and sees Mistress "Greetings Mistress."

NodeJS: What is the proper way to handling TCP socket streams ? Which delimiter should I use?

From what I understood here, "V8 has a generational garbage collector. Moves objects aound randomly. Node can’t get a pointer to raw string data to write to socket." so I shouldn't store data that comes from a TCP stream in a string, specially if that string becomes bigger than Math.pow(2,16) bytes. (hope I'm right till now..)
What is then the best way to handle all the data that's comming from a TCP socket ? So far I've been trying to use _:_:_ as a delimiter because I think it's somehow unique and won't mess around other things.
A sample of the data that would come would be something_:_:_maybe a large text_:_:_ maybe tons of lines_:_:_more and more data
This is what I tried to do:
net = require('net');
var server = net.createServer(function (socket) {
socket.on('connect',function() {
console.log('someone connected');
buf = new Buffer(Math.pow(2,16)); //new buffer with size 2^16
socket.on('data',function(data) {
if (data.toString().search('_:_:_') === -1) { // If there's no separator in the data that just arrived...
buf.write(data.toString()); // ... write it on the buffer. it's part of another message that will come.
} else { // if there is a separator in the data that arrived
parts = data.toString().split('_:_:_'); // the first part is the end of a previous message, the last part is the start of a message to be completed in the future. Parts between separators are independent messages
if (parts.length == 2) {
msg = buf.toString('utf-8',0,4) + parts[0];
console.log('MSG: '+ msg);
buf = (new Buffer(Math.pow(2,16))).write(parts[1]);
} else {
msg = buf.toString() + parts[0];
for (var i = 1; i <= parts.length -1; i++) {
if (i !== parts.length-1) {
msg = parts[i];
console.log('MSG: '+msg);
} else {
buf.write(parts[i]);
}
}
}
}
});
});
});
server.listen(9999);
Whenever I try to console.log('MSG' + msg), it will print out the whole buffer, so it's useless to see if something worked.
How can I handle this data the proper way ? Would the lazy module work, even if this data is not line oriented ? Is there some other module to handle streams that are not line oriented ?
It has indeed been said that there's extra work going on because Node has to take that buffer and then push it into v8/cast it to a string. However, doing a toString() on the buffer isn't any better. There's no good solution to this right now, as far as I know, especially if your end goal is to get a string and fool around with it. Its one of the things Ryan mentioned # nodeconf as an area where work needs to be done.
As for delimiter, you can choose whatever you want. A lot of binary protocols choose to include a fixed header, such that you can put things in a normal structure, which a lot of times includes a length. In this way, you slice apart a known header and get information about the rest of the data without having to iterate over the entire buffer. With a scheme like that, one can use a tool like:
node-buffer - https://github.com/substack/node-binary
node-ctype - https://github.com/rmustacc/node-ctype
As an aside, buffers can be accessed via array syntax, and they can also be sliced apart with .slice().
Lastly, check here: https://github.com/joyent/node/wiki/modules -- find a module that parses a simple tcp protocol and seems to do it well, and read some code.
You should use the new stream2 api. http://nodejs.org/api/stream.html
Here are some very useful examples: https://github.com/substack/stream-handbook
https://github.com/lvgithub/stick