Two Plus Two Publishing LLC
Two Plus Two Publishing LLC
 

Go Back   Two Plus Two Poker Forums > >

Notices

Programming Discussions about computer programming

Reply
 
Thread Tools Display Modes
Old Yesterday, 06:59 AM   #33401
cannabusto
Pooh-Bah
 
Join Date: Jan 2013
Posts: 3,982
Re: ** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD **

I couldn't agree more on the pm stuff. Thought it was just me.
cannabusto is offline   Reply With Quote
Old Yesterday, 10:46 AM   #33402
suzzer99
Carpal \'Tunnel
 
suzzer99's Avatar
 
Join Date: Nov 2005
Location: on top of the bell curve
Posts: 85,324
Re: ** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD **

AirBnb goes all in on react native, 2 years later pulls out and goes back to regular mobile: https://medium.com/airbnb-engineerin...e-1868ba28e30a

I feel like this the arc for so many front end frameworks and web/mobile solutions like phone gap and react native. There's so many latest and greatest front end frameworks I wanted to learn at an industrial scale, but then wasn't too upset when they fell out of favor.

I can tell you a lot about debugging Android native browser and chrome circa 2010-2013 - particularly with Sencha Touch. That knowledge does me **** all good now.
suzzer99 is offline   Reply With Quote
Old Yesterday, 12:20 PM   #33403
Wolfram
Carpal \'Tunnel
 
Wolfram's Avatar
 
Join Date: Jan 2006
Location: You can be my wingman any time
Posts: 14,618
Re: ** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD **

The dream of write once, run anywhere is in an endless cycle of rebirth and death.
Wolfram is offline   Reply With Quote
Old Yesterday, 12:28 PM   #33404
blackize5
old hand
 
Join Date: Sep 2012
Posts: 1,203
Re: ** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD **

Yeah we're talking about the Airbnb thing at work. There's a couple guys who just love latest stuff and are always pushing to redo our apps with react native.

And of course they only read the easily digestible last article in the series then say things like "welp I wonder what their real reasons are?" When I link the article that details all the technical pros and cons they latch on to the type safety complaint and dismiss the whole thing with "guess they just don't like JS." ****.
blackize5 is offline   Reply With Quote
Old Yesterday, 01:12 PM   #33405
suzzer99
Carpal \'Tunnel
 
suzzer99's Avatar
 
Join Date: Nov 2005
Location: on top of the bell curve
Posts: 85,324
Re: ** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD **

Quote:
Originally Posted by Wolfram View Post
The dream of write once, run anywhere is in an endless cycle of rebirth and death.
Web-apps were getting pretty close before mobile came along. Pretty much all the remaining browser differences were abstracted out by stuff like jQuery. Responsive seemed to work fairly well when screen sizes vary only from laptop to big monitor.

Also for most run of the mill back end apps - the JVM is certainly an improvement over C++ native OS libraries.

So WORA can work in fits and starts. But the big miracle breakthrough that IT managers love to fap to never seems to work out.
suzzer99 is offline   Reply With Quote
Old Yesterday, 07:02 PM   #33406
goofyballer
 
goofyballer's Avatar
 
Join Date: Jun 2005
Posts: 62,548
Re: ** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD **

Twitter bot is working, code if anyone's curious

main.go (lambda handler, general glue):

Code:
package main

import (
	"fmt"
	"log"
	"os"

	"github.com/aws/aws-lambda-go/lambda"
)

func main() {
	lambda.Start(Handler)
}

func Handler() {
	str, err := GetS3File("tweet.txt")
	if err != nil {
		return
	}
	log.Println("Read string:", str)

	tweet, err := GetNextTweet(str)
	if err != nil {
		log.Println("Twitter error:", err)
	}
	if tweet == nil {
		log.Println("No tweet found, exiting")
		return
	}
	log.Println("next oldest id: ", tweet.IdStr())

	err = UpdateS3File("tweet.txt", tweet.IdStr())
	if err != nil {
		log.Println("Error updating file:", err)
	}

	var token string
	cookieJson, err := GetS3File("cookies.txt")
	if err != nil {
		fmt.Println("no cookies, will log in")
	} else {
		token, err = GetS3File("token.txt")
		if err != nil {
			fmt.Println("no cached token, will have to grab")
		}
	}

	threadID, ok := os.LookupEnv("FORUM_THREAD_ID")
	if !ok {
		fmt.Println("No thread ID found")
		return
	}
	var client *ForumClient
	if cookieJson != "" {
		client, err = NewClientWithJsonCookies(cookieJson)
	} else {
		user, ok := os.LookupEnv("FORUM_USERNAME")
		if !ok {
			fmt.Println("No username found")
			return
		}
		pass, ok := os.LookupEnv("FORUM_PASSWORD")
		if !ok {
			fmt.Println("No password found")
			return
		}
		client, err = NewClientWithLogin(user, pass)
	}
	if err != nil {
		fmt.Println("Error getting client:", err)
		return
	}

	tokenWasEmpty := token == ""
	client.Token = token
	postContent := fmt.Sprintf("[tweet ]%s[/ tweet]\n%s", tweet.IdStr(), TweetLink(tweet.IdStr()))
	err = client.SubmitNewPost(postContent, threadID)
	if err != nil {
		fmt.Println("Error submitting post:", err)
		return
	}

	updatedJSON, err := JsonFromCookies(client.Client.Jar)
	if err != nil {
		fmt.Println("Error getting cookies:", err)
		return
	}

	err = UpdateS3File("cookies.txt", updatedJSON)
	if err != nil {
		fmt.Println("Error updating S3 cookies:", err)
		return
	}

	if tokenWasEmpty && client.Token != "" {
		err = UpdateS3File("token.txt", client.Token)
		if err != nil {
			fmt.Println("Error updating token:", err)
		}
	}
}
aws.go (s3 access):

Code:
package main

import (
	"log"
	"strings"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/s3"
	"github.com/aws/aws-sdk-go/service/s3/s3manager"
)

var sharedSession *session.Session

func getSession() *session.Session {
	if sharedSession == nil {
		sharedSession = session.New(&aws.Config{Region: aws.String("us-east-2")})
	}
	return sharedSession
}

func GetS3File(filename string) (string, error) {
	sess := getSession()
	downloader := s3manager.NewDownloader(sess)
	buf := aws.NewWriteAtBuffer([]byte{})
	_, err := downloader.Download(buf, &s3.GetObjectInput{
		Bucket: aws.String("mybotbucket"), // TODO: parameterize
		Key:    aws.String(filename),
	})
	if err != nil {
		log.Println("download err:", err)
		return "", err
	}
	return string(buf.Bytes()), nil
}

func UpdateS3File(filename, content string) error {
	sess := getSession()
	uploader := s3manager.NewUploader(sess)
	_, err := uploader.Upload(&s3manager.UploadInput{
		Bucket: aws.String("mybotbucket"),
		Key:    aws.String(filename),
		Body:   strings.NewReader(content),
	})
	return err
}
twitter.go (get latest trump tweet) (some of this copypastaed from examples that I'm too lazy to update):

Code:
package main

import (
	"errors"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"os"

	"github.com/kurrik/oauth1a"
	"github.com/kurrik/twittergo"
)

func LoadEnvCredentials() (*oauth1a.ClientConfig, error) {
	key, ok := os.LookupEnv("TWITTER_CONSUMER_KEY")
	if !ok {
		return nil, errors.New("no key")
	}
	secret, ok := os.LookupEnv("TWITTER_CONSUMER_SECRET")
	if !ok {
		return nil, errors.New("no secret")
	}
	config := &oauth1a.ClientConfig{
		ConsumerKey:    key,
		ConsumerSecret: secret,
	}
	return config, nil
}

var NoResults = errors.New("No search results")

func GetNextTweet(baseId string) (*twittergo.Tweet, error) {
	config, err := LoadEnvCredentials()
	if err != nil {
		log.Println("Twitter config error:", err)
		return nil, err
	}
	client := twittergo.NewClient(config, nil)

	var (
		req     *http.Request
		resp    *twittergo.APIResponse
		query   url.Values
		results *twittergo.Timeline
	)
	const urltmpl = "/1.1/statuses/user_timeline.json?%v"
	query = url.Values{}
	query.Set("count", "200")
	query.Set("screen_name", "realDonaldTrump")
	query.Set("tweet_mode", "extended")
	query.Set("trim_user", "1")
	query.Set("exclude_replies", "1")
	query.Set("include_rts", "0")
	if baseId != "" {
		query.Set("since_id", baseId)
	}

	endpoint := fmt.Sprintf(urltmpl, query.Encode())
	if req, err = http.NewRequest("GET", endpoint, nil); err != nil {
		log.Printf("Could not parse request: %v\n", err)
		os.Exit(1)
	}
	if resp, err = client.SendRequest(req); err != nil {
		log.Printf("Could not send request: %v\n", err)
		os.Exit(1)
	}
	results = &twittergo.Timeline{}
	if err = resp.Parse(results); err != nil {
		if rle, ok := err.(twittergo.RateLimitError); ok {
			msg := "Rate limited. Reset at %v\n"
			log.Printf(msg, rle.Reset)
		} else {
			log.Printf("Problem parsing response: %v\n", err)
		}
		return nil, err
	}
	batch := len(*results)
	if batch == 0 {
		log.Printf("No more results, end of timeline.\n")
		return nil, NoResults
	}

	var oldest *twittergo.Tweet
	for _, tweet := range *results {
		if oldest == nil || tweet.CreatedAt().Before(oldest.CreatedAt()) {
			oldest = &tweet
		}
	}

	return oldest, nil
}

func TweetLink(id string) string {
	return fmt.Sprintf("https://twitter.com/realDonaldTrump/status/%s", id)
}
forum.go - for posting stuff to 2+2, definitely took the most time (and borrowed a lot from what Chips' code was doing, thanks for the help WN)

Code:
package main

import (
	"bytes"
	"crypto/md5"
	"encoding/hex"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"regexp"
	"strings"
)

type ForumClient struct {
	Client *http.Client
	Token  string
}

// NewClientWithLogin will attempt a fresh login on the forum with the given
// username and password, seeding the returned http.Client with the cookies
// needed to make future authenticated requests
func NewClientWithLogin(username, password string) (*ForumClient, error) {
	client, err := newClient()
	if err != nil {
		return nil, err
	}

	// load 2+2 to seed initial cookies
	resp, err := client.Get(forumURL)
	if err != nil {
		fmt.Println("forum load error:", err)
		return nil, err
	}

	// get session token
	var sessionToken string
	for _, cookie := range resp.Cookies() {
		if cookie.Name == "bbsessionhash" {
			sessionToken = cookie.Value
			break
		}
	}

	// get md5 password
	hasher := md5.New()
	_, err = hasher.Write([]byte(password))
	if err != nil {
		return nil, err
	}
	md5pass := hex.EncodeToString(hasher.Sum(nil))

	// set up login form
	vals := url.Values{
		"do":                       {"login"},
		"cookieuser":               {"1"},
		"securitytoken":            {"guest"},
		"vb_login_md5password":     {md5pass},
		"vb_login_md5password_utf": {md5pass},
		"vb_login_password":        {""},
		"vb_login_username":        {username},
		"s":                        {sessionToken},
	}

	req, err := http.NewRequest("POST", loginURL, strings.NewReader(vals.Encode()))
	if err != nil {
		return nil, err
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0")
	req.Header.Set("Referer", forumURL)

	_, err = client.Do(req)
	if err != nil {
		fmt.Println("login err:", err)
		return nil, err
	}
	return &ForumClient{Client: client}, nil
}

func NewClientWithCookies(cookies []*http.Cookie) (*ForumClient, error) {
	client, err := newClient()
	if err != nil {
		return nil, err
	}
	parsedURL, err := url.Parse(forumURL)
	if err != nil {
		return nil, err
	}
	client.Jar.SetCookies(parsedURL, cookies)
	return &ForumClient{Client: client}, nil
}

func NewClientWithJsonCookies(cookieJson string) (*ForumClient, error) {
	decoder := json.NewDecoder(strings.NewReader(cookieJson))
	cookies := make([]*http.Cookie, 0)
	err := decoder.Decode(&cookies)
	if err != nil {
		return nil, err
	}
	return NewClientWithCookies(cookies)
}

func JsonFromCookies(jar http.CookieJar) (string, error) {
	parsedURL, err := url.Parse(forumURL)
	if err != nil {
		return "", err
	}
	var buf bytes.Buffer
	encoder := json.NewEncoder(&buf)
	err = encoder.Encode(jar.Cookies(parsedURL))
	if err != nil {
		return "", err
	}
	return buf.String(), nil
}

func (c *ForumClient) SubmitNewPost(content, threadId string) error {
	destURL := forumURL + fmt.Sprintf("/newreply.php?do=postreply&t=%s", threadId)

	uid, err := cookieByName(c.Client.Jar, "bbuserid")
	if err != nil {
		return err
	}

	if c.Token == "" {
		token, err := getSecurityToken(c.Client)
		if err != nil {
			return err
		}
		c.Token = token
	}

	vals := url.Values{
		"do":              {"postreply"},
		"emailupdate":     {"0"},
		"iconid":          {"0"},
		"loggedinuser":    {uid.Value},
		"message":         {content},
		"multiquoteempty": {},
		"p":               {},
		"parseurl":        {"1"},
		"posthash":        {"invalid+posthash"},
		"poststarttime":   {"0"},
		"rating":          {"0"},
		"s":               {},
		"sbutton":         {"Submit+Reply"},
		"securitytoken":   {c.Token},
		"t":               {threadId},
		"title":           {},
		"wysiwyg":         {"0"},
	}

	req, err := http.NewRequest("POST", destURL, strings.NewReader(vals.Encode()))
	if err != nil {
		return err
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0")
	req.Header.Set("Referer", destURL)

	_, err = c.Client.Do(req)
	if err != nil {
		return err
	}

	return nil
}

const forumURL = "https://forumserver.twoplustwo.com"
const loginURL = "https://forumserver.twoplustwo.com/login.php?do=login"

func newClient() (*http.Client, error) {
	jar, err := cookiejar.New(nil)
	if err != nil {
		return nil, err
	}
	client := &http.Client{Jar: jar}
	client.CheckRedirect = func(*http.Request, []*http.Request) error { return http.ErrUseLastResponse }
	return client, nil
}

func cookieByName(jar http.CookieJar, name string) (*http.Cookie, error) {
	if jar == nil {
		return nil, errors.New("nil jar")
	}
	parsed, err := url.Parse(forumURL)
	if err != nil {
		return nil, err
	}
	for _, cookie := range jar.Cookies(parsed) {
		if cookie.Name == name {
			return cookie, nil
		}
	}
	return nil, fmt.Errorf("cookie not found: %s", name)
}

var securityRegex = regexp.MustCompile(`var SECURITYTOKEN = "([0-9a-z\-_]+)"`)

func getSecurityToken(client *http.Client) (string, error) {
	resp, err := client.Get(forumURL + "/private.php")
	if err != nil {
		return "", err
	}
	buf, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}
	resp.Body.Close()

	token := securityRegex.FindStringSubmatch(string(buf))
	if token == nil || len(token) <= 1 {
		return "", errors.New("token not found")
	}
	return token[1], nil
}

Last edited by goofyballer; Yesterday at 07:19 PM.
goofyballer is offline   Reply With Quote
Old Yesterday, 07:30 PM   #33407
jmakin
 
jmakin's Avatar
 
Join Date: Jan 2008
Location: Streaming
Posts: 27,750
Re: ** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD **

nice work
jmakin is offline   Reply With Quote
Old Yesterday, 09:44 PM   #33408
goofyballer
 
goofyballer's Avatar
 
Join Date: Jun 2005
Posts: 62,548
Re: ** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD **

Damn, got an error with security token caching: "Your submission could not be processed because the token has expired." Are those supposed to be short-lived? Not like session tokens? It's a lot faster if I cache that one (don't have to load a random 2+2 page to re-read it), but I guess maybe I can't
goofyballer is offline   Reply With Quote
Old Yesterday, 10:00 PM   #33409
well named
poorly undertitled
 
well named's Avatar
 
Join Date: Jun 2007
Location: esse est coesse
Posts: 73,890
Re: ** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD **

Yeah, that's the thing I was saying before I wasn't sure about off the top of my head. They might be like CSRF tokens and have a short lifespan.

edit: Pretty cool stuff btw!
well named is offline   Reply With Quote
Old Yesterday, 11:14 PM   #33410
_dave_
_Pooh_Bah_
 
Join Date: Feb 2005
Location: UK (or what remains of it)
Posts: 12,636
Re: ** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD **

I know if I try and post a reply to a thread I had open in a tab yesterday (manual, using Firefox), I'll get that token error if I don't reload the page.
_dave_ is offline   Reply With Quote
Old Today, 06:13 AM   #33411
SiQ
Carpal \'Tunnel
 
Join Date: Jan 2008
Location: still ahead of the game
Posts: 7,160
Re: ** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD **

Virustotal is starting a service called "Monitor" where you can upload files to be monitored for positive hits. It will also apparently do the annoying work of submitting samples to all those AVs.
Pretty cool news for smaller projects and solo devs like me. Still waiting for the service to be available (and pricing).

https://techcrunch.com/2018/06/19/vi...lse-positives/

SiQ is offline   Reply With Quote
Old Today, 08:34 AM   #33412
Wolfram
Carpal \'Tunnel
 
Wolfram's Avatar
 
Join Date: Jan 2006
Location: You can be my wingman any time
Posts: 14,618
Re: ** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD **

Goofy,
Cool app. Looks like you are pretty all-in on Go. I'm still just using for hobby projects so it might just be the honeymoon effect but so far I really love it.

What's been your experience as a professional developer. Any obvious pros/cons?
Wolfram is offline   Reply With Quote
Old Today, 09:24 AM   #33413
RustyBrooks
Carpal \'Tunnel
 
RustyBrooks's Avatar
 
Join Date: Feb 2006
Location: Austin, TX
Posts: 23,587
Re: ** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD **

Quote:
Originally Posted by SiQ View Post
Virustotal is starting a service called "Monitor" where you can upload files to be monitored for positive hits. It will also apparently do the annoying work of submitting samples to all those AVs.
Pretty cool news for smaller projects and solo devs like me. Still waiting for the service to be available (and pricing).
This is on my list of things to do for our product. If I ever get to it, hopefully it'll be free.
RustyBrooks is offline   Reply With Quote
Old Today, 01:08 PM   #33414
Barrin6
Carpal \'Tunnel
 
Barrin6's Avatar
 
Join Date: Dec 2005
Location: beyond legal blindness
Posts: 6,788
Re: ** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD **

I’m going to bring it up on my retro but do you guys ever have problems getting reviews for your PR? I consistently always get the same two people to review my PR in a timely manner. But since these two people are out for most of this sprint, I have been blocked twiddling my thumbs.

Currently sitting at 7 PRs waiting for review.
Barrin6 is offline   Reply With Quote
Old Today, 01:10 PM   #33415
well named
poorly undertitled
 
well named's Avatar
 
Join Date: Jun 2007
Location: esse est coesse
Posts: 73,890
Re: ** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD **

Sometimes our PRs get backed up. Especially more complicated ones. We use slack to harass people to do reviews. I've never gotten up to 7 pending though. I think it's probably inevitable that there will always be some friction when it's easy to get head down trying to get your own stuff done. But yeah people have to schedule at least some time on a regular basis and do reviews.
well named is offline   Reply With Quote
Old Today, 01:13 PM   #33416
PJo336
THRILLHOUSE!
 
PJo336's Avatar
 
Join Date: Mar 2007
Posts: 21,533
Re: ** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD **

Yup been there. Definitely say something. We had to have a convo around
A) setting time aside specifically for reviews
B) not just having certain people only review for other certain people, ie tony always reviews mine but steve never does, etc
C) Making PRs smaller when possible to make review context easier
PJo336 is offline   Reply With Quote
Old Today, 01:22 PM   #33417
Barrin6
Carpal \'Tunnel
 
Barrin6's Avatar
 
Join Date: Dec 2005
Location: beyond legal blindness
Posts: 6,788
Re: ** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD **

Yea and then what ends up happening is that we are near the sprint and everyone just half ass approves just to get it over the finish line.
Barrin6 is offline   Reply With Quote

Reply
      

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off


Forum Jump


All times are GMT -4. The time now is 01:39 PM.


Powered by vBulletin®
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.
Copyright ę 2008-2017, Two Plus Two Interactive
 
 
Poker Players - Streaming Live Online