Open Side Menu Go to the Top
Register
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** ** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD **

06-20-2018 , 06:59 AM
I couldn't agree more on the pm stuff. Thought it was just me.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
06-20-2018 , 10:46 AM
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.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
06-20-2018 , 12:20 PM
The dream of write once, run anywhere is in an endless cycle of rebirth and death.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
06-20-2018 , 12:28 PM
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." ****.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
06-20-2018 , 01:12 PM
Quote:
Originally Posted by Wolfram
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.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
06-20-2018 , 07:02 PM
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; 06-20-2018 at 07:19 PM.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
06-20-2018 , 07:30 PM
nice work
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
06-20-2018 , 09:44 PM
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
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
06-20-2018 , 10:00 PM
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!
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
06-20-2018 , 11:14 PM
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.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
06-21-2018 , 06:13 AM
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/

** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
06-21-2018 , 08:34 AM
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?
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
06-21-2018 , 09:24 AM
Quote:
Originally Posted by SiQ
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.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
06-21-2018 , 01:08 PM
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.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
06-21-2018 , 01:10 PM
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.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
06-21-2018 , 01:13 PM
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
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
06-21-2018 , 01:22 PM
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.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
06-21-2018 , 02:32 PM
Wonder if I'm doing something wrong then. I'm the lead for my team and I don't let people's PR last longer than a day without a review, but my "review" is basically look at the diff and see if I can see something endemically wrong i.e. a "deep lint". I don't bother with going farther than that.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
06-21-2018 , 02:41 PM
We use scrum / standup to make sure every PR has a reviewer. Some things are reviewed before that (people will often ask for reviews when they need one), but this way we're guaranteed to assign a reviewer within a day. Most people then do the reviews pretty quickly and its fairly rare for them to go longer than 1-2 days (and usually when it takes longer its because of me).

I don't agree with "deep lint" style reviews. Those comments are fine, but for reviews to be really worth it I think they generally need to go deeper. And if nobody is qualified to understand a deep review then the person making the PR should have to explain it / walk through it.

I also don't think team leads (or whatever) need to review everything.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
06-21-2018 , 03:10 PM
Quote:
Originally Posted by Wolfram
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?
I generally try to pick the right tool for the task, and in this case I felt Go was something I could get started with quickly since I'm using it day to day and I know (because coworkers were excited about this last year) that AWS has Go support.

It's pretty nice in general, but one thing that hurts is the lack of generics, and it feels like you spend too much time putting bandaids on problems because of it. For example, a coworker posted this yesterday when we were discussing how to clean up an API that was repeating a lot of code between two functions that essentially did the same thing, but with different types: Closures are the Generics for Go

This is like "hey you don't need generics if you do stuff with closures", and yet, this is what their solution was:

Code:
func buildCompleteList(process func(opts *github.ListOptions) (*github.Response, error)) (*github.Response, error)
The only reason this works is because every functor they would pass into this does a similar operation and returns the same type (*github.Response); this is not generalized. Every other modern language with type safety (C++, C#, Java, and I'm sure others I haven't used) have figured out how to generalize algorithms while abstracting types without ruining the language in the process, and Go making you cast things down to interface{} is just a total pile of ****. Or stuff like this: https://play.golang.org/p/zNJ2SGZkX4D

Why can't this program compile? Why can't a channel of integers be used to feed values into a function that does not give a **** what type of objects it receives?

Why does the signature for sort.Slice have to be this:

Code:
func Slice(slice interface{}, less func(i, j int) bool)
Right, because the language doesn't allow you to pass a general slice as a []interface{}, so the only workaround is for this function to accept literally any type as an argument and panic (at runtime) if you don't give it a slice. So, type safety gets hurt by their intransigence for adding language features.

So, sometimes you hit stuff like this that's super frustrating, and you're definitely more likely to hit these things (or at least care about them) in large systems. Like all languages, Go isn't perfect, and it comes with a very opinionated toolset that definitely isn't perfect. I imagine they'll soon enough learned the same thing Java learned (no matter how hard you try, your language will suffer without generics) and Go will be a lot better off for it.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
06-21-2018 , 04:08 PM
Quote:
Originally Posted by goofyballer
Why does the signature for sort.Slice have to be this:

Code:
func Slice(slice interface{}, less func(i, j int) bool)
Right, because the language doesn't allow you to pass a general slice as a []interface{}, so the only workaround is for this function to accept literally any type as an argument and panic (at runtime) if you don't give it a slice. So, type safety gets hurt by their intransigence for adding language features.
Expanding on this, I was so busy hating on the first parameter I didn't even notice the second: in any other sane language this would be a comparison function between two objects of the type contained in the slice. But you can't do that in Go, so instead Go will pass your comparator the indices in the slice, which means that every comparator you ever pass to this would have to be a closure containing the first parameter you already passed in. And even this ****ty, verbose solution is so cutting-edge and revolutionary to Go that it was added to the standard library in version 1.8 of the language, just 16 months ago.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
06-21-2018 , 06:03 PM
Quote:
Originally Posted by Grue
Wonder if I'm doing something wrong then. I'm the lead for my team and I don't let people's PR last longer than a day without a review, but my "review" is basically look at the diff and see if I can see something endemically wrong i.e. a "deep lint". I don't bother with going farther than that.
Same here. I basically look for code issues. We have SQA to make sure the functionality works. W/o SQA - whole different story obviously.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
06-21-2018 , 06:06 PM
I always assign people to review or do it myself if it’s something easy

We have a fairly extensive automated regression testing system in place too

Btw i found out today i’m basically the replacement for the rockstar leaving in september. So i asked my boss if i could focus mostly on programming and he said yes that would be ideal
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
06-22-2018 , 02:30 AM
Awesome! Time to learn and make some mistakes!

I was still blocked today so I devoted some of my time pairing with the other person on my team and the intern. I feel bad for the intern because she got thrown into a project that only my boss has strong domain knowledge on and he’s always unavailable.

Also we have another new grad on my team who started this week, so have been helping that person getting ramped up. It’s anazing how much time you can kill just mentoring and pairing with people. Though it’s a nice break from keeping your head down and programming.

The team lead should be back tomorrow so I should be unblocked once he reviews my PRs.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
06-22-2018 , 06:46 AM
Quote:
Originally Posted by jmakin
I
Btw i found out today i’m basically the replacement for the rockstar leaving in september. So i asked my boss if i could focus mostly on programming and he said yes that would be ideal
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote

      
m